以下は、この問題に関連する記事の一部の無料翻訳です。
タイプチェックFS
最初のステップは、ファイルシステムが代替ストリームをサポートしているかどうかを確認することです。それ以外の場合、それらを操作しようとする意味はありません。
char szVolName[MAX_PATH], szFSName[MAX_PATH];
DWORD dwSN, dwMaxLen, dwVolFlags;
::GetVolumeInformation("C:\\", szVolName, MAX_PATH, &dwSN,
&dwMaxLen, &dwVolFlags, szFSName, MAX_PATH);
if (dwVolFlags & FILE_NAMED_STREAMS)
{
// File system supports named streams
}
else
{
// Named streams are not supported
}
* This source code was highlighted with Source Code Highlighter .
代替ストリームの作成
通常のファイルと同様に、CreateFile関数を使用して代替ストリームを作成できます。
HANDLE hFile = ::CreateFile( "file.dat:alt" , ...
ファイルが存在しなかった場合、メインストリームの指定された名前を持つ長さゼロのファイルが作成されます。
代替ストリームの削除
代替ストリームを削除することは、通常のファイルを削除することほど難しくありません。 ストリームを完全にサポートするDeleteFile関数は、これに適しています。
::DeleteFile( "file.dat:alt" );
標準ストリームを削除すると、その代替ストリームもすべて削除されます。
代替ストリームをコピー
代替ストリームをコピーするには、Win32 APIのCopyFile / CopyFileEx関数を使用できます。 ただし、これらの関数は予期しない結果を生じる可能性があります。 コピーには2つのオプションがあります。
標準ストリームから標準ストリームへ:通常のファイル操作。ファイルとともにすべての名前付きストリームがコピーされます。 ファイルが存在する場合は、置き換えられます。
名前付きストリームから標準ストリームへ:この場合、選択されたストリームのみがコピーされます。 宛先ファイルが存在する場合、すべてのストリーム(存在する場合)とともに削除され、新しいファイルはコピーが行われる標準ストリームのみで作成されます。
単純な読み取り/書き込みサイクルでコピーすると、期待される結果が得られます。
HANDLE hInFile = ::CreateFile(szFromStream, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
HANDLE hOutFile = ::CreateFile(szToStream, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
BYTE buf[64*1024];
DWORD dwBytesRead, dwBytesWritten;
do
{
::ReadFile(hInFile, buf, sizeof (buf), &dwBytesRead, NULL);
if (dwBytesRead) ::WriteFile(hOutFile, buf, dwBytesRead, &dwBytesWritten, NULL);
}
while (dwBytesRead == sizeof (buf));
::CloseHandle(hInFile);
::CloseHandle(hOutFile);
* This source code was highlighted with Source Code Highlighter .
スレッドのリスト
ネイティブAPIのいくつかの機能を使用して、スレッドのリストを取得できます。 以下は、ファイルからストリームのリストを取得するためのコードです。
// Open a file and obtain stream information
BYTE InfoBlock[64 * 1024]; // Buffer must be large enough
PFILE_STREAM_INFORMATION pStreamInfo = (PFILE_STREAM_INFORMATION)InfoBlock;
IO_STATUS_BLOCK ioStatus;
HANDLE hFile = ::CreateFile(szPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
NtQueryInformationFile(hFile, &ioStatus, InfoBlock,
sizeof (InfoBlock), FileStreamInformation);
::CloseHandle(hFile);
* This source code was highlighted with Source Code Highlighter .
ディレクトリフローのリストを取得する状況はより複雑です。
// Open a directory and obtain stream information
// Obtain backup privilege in case we don't have it
HANDLE hToken;
TOKEN_PRIVILEGES tp;
::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
::LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (TOKEN_PRIVILEGES), NULL, NULL);
::CloseHandle(hToken);
HANDLE hFile = ::CreateFile(szPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
BYTE InfoBlock[64 * 1024]; // Buffer must be large enough
PFILE_STREAM_INFORMATION pStreamInfo = (PFILE_STREAM_INFORMATION)InfoBlock;
IO_STATUS_BLOCK ioStatus;
pStreamInfo->StreamNameLength = 0; // Zero in this field means empty info block
NtQueryInformationFile(hFile, &ioStatus, InfoBlock,
sizeof (InfoBlock), FileStreamInformation);
::CloseHandle(hFile);
* This source code was highlighted with Source Code Highlighter .
これで、ファイル/ディレクトリに関する情報を受け取ったので、リスト自体を表示できます。
WCHAR wszStreamName[MAX_PATH];
for (;;)
{
// Check if stream info block is empty (directory may have no stream)
if (pStreamInfo->StreamNameLength == 0) break ; // No stream found
// Get null-terminated stream name
memcpy(wszStreamName, pStreamInfo->StreamName, pStreamInfo->StreamNameLength);
wszStreamName[pStreamInfo->StreamNameLength / sizeof (WCHAR)] = L '\0' ;
print( "%S" , wszStreamName);
if (pStreamInfo->NextEntryOffset == 0) break ; // No more stream records
pStreamInfo = (PFILE_STREAM_INFORMATION)
((LPBYTE)pStreamInfo + pStreamInfo->NextEntryOffset); // Next stream record
}
* This source code was highlighted with Source Code Highlighter .
VC ++コンソールの例