VC++ 基于NTFS的数据流创建与检测
#include
int ReadStream( HANDLE hFile, bool bIsDirectory, char* FileName )
{
//数据流文件名查找
//
//输入:
// 已打开的文件句柄
// bIsDirectory
// 文件名, 用于显示数据流在哪个文件中
//结果:
// 直接在函数中输出
//返回:
// Count:数据流的个数
WIN32_STREAM_ID sid; //数据流头结构
LPVOID lpContext = NULL; //环境指针,读取数据流时,必须为空
DWORD dwRead = 1; //实际读取的大小
int Success;
int Count = 0; //数据流的个数
UCHAR *Buffer; //动态分配的空间指针
bool bIsFirst = true; //是否为所查找到的第一个数据流名
ZeroMemory( &sid, sizeof( WIN32_STREAM_ID ) ); //清空sid
//数据流头大小,实际为20字节
DWORD dwStreamHeaderSize = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid;
/*
if( strcmp( FileName, "F://VC 6//Contrl控制台程序//DataStreamFinder//test//test//Last.txt" ) == 0 )
{
//打印出所有流字符
UCHAR *Buffer1 = (UCHAR*)malloc(50000);
memset( Buffer1, 0, 50000);
Success = ::BackupRead( hFile, (LPBYTE)Buffer1, 50000, &dwRead, false, false, &lpContext );
printf( "Size of Head: %d/n", dwStreamHeaderSize );
for( unsigned int i=0; i<dwRead; i ++ )
{
printf( "(%d)%c", i, Buffer1[i] );
}
printf( "/n" );
return 0;
}
*/
if( !bIsDirectory ) //如果不是目录,就执行此段
{
//读取原始文件头
Success = ::BackupRead( hFile, (LPBYTE)&sid, dwStreamHeaderSize, &dwRead, false, false, &lpContext );
if( !Success ) //读取原始文件头失败
{
return 0;
}
//读取源文件内容
char Len64[25];
DWORD OrgFileLen;
ZeroMemory( Len64, sizeof( Len64 ) );
//将i64转为DWORD型
sprintf( Len64, "%u", sid.Size );
OrgFileLen = atol( Len64 );
//跳过文件内容
DWORD FileLenL, FileLenH;
Success = ::BackupSeek( hFile, OrgFileLen, NULL, &FileLenL, &FileLenH, &lpContext );
if( !Success )
{
return 0;
}
}
while( dwRead )
{
//读取源文件内容
char Len64[25];
DWORD OrgFileLen;
//读取数据流头
Success = ::BackupRead( hFile, (LPBYTE)&sid, dwStreamHeaderSize, &dwRead, false, false, &lpContext );
if( !Success )
{
break;
}
//读取数据流名称
Buffer = (UCHAR*)malloc( sid.dwStreamNameSize + 2 ); //动态申请缓存
memset( Buffer, 0, sid.dwStreamNameSize + 2 ); //缓存清空
Success = ::BackupRead( hFile, (LPBYTE)Buffer, sid.dwStreamNameSize, &dwRead, false, false, &lpContext );
if( !Success )
{
free( Buffer ); //释放缓存
break;
}
if( dwRead ) //读取数不为0
{
if( bIsFirst ) //输出的第一个数据流名
{
printf( "/"%s/" Have Data Stream:/n", FileName );
bIsFirst = false;
}
//读取数据流文件内容大小
ZeroMemory( Len64, sizeof( Len64 ) );
//将i64转为DWORD型
sprintf( Len64, "%u", sid.Size );
OrgFileLen = atol( Len64 );
printf( "/t/t[%ws] -> %u Byte/n", Buffer, OrgFileLen ); //结果输出,直接输出数据流名称,用空格分隔
free( Buffer ); //释放缓存
Count ++; //数据流个数加1
}
//跳过数据流文件内容
DWORD FileLenL, FileLenH;
Success = ::BackupSeek( hFile, OrgFileLen, NULL, &FileLenL, &FileLenH, &lpContext );
if( !Success )
{
break;
}
}
return Count;
}
void GetFileDataStream( char* FileName, bool bIsDirectory )
{
//传入参数
// FileName 要检测的文件名或目录名
// bIsDirectory, 若是目录,则应为 true, 否则应为 false
int Count;
HANDLE hFile = ::CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
printf( "ERROR When Open File /"%s/"!/n", FileName );
return ;
}
if( !bIsDirectory ) //不是目录
{
DWORD dwFileSize;
dwFileSize = ::GetFileSize( hFile, NULL ); //得到文件大小
if( dwFileSize >= 0x80000000 ) //文件太大,不分析(>=2G)
{
::CloseHandle( hFile );
printf( "File /"%s/" Too Big, Ignore It! (大于2G)/n", FileName );
return ;
}
if( dwFileSize == 0 ) //大小为0
{
bIsDirectory = true; //如果文件大小为0,则按目录方面来处理
}
}
Count = ReadStream( hFile, bIsDirectory, FileName );
if( Count )
{
printf( "/t/t/tCount of Data Stream: %d/n/n", Count );
}
::CloseHandle( hFile );
}
void FindAllFilesInDirectory( char* Dir, bool bIsRecursion )
{
//查找当前目录下的所有文件和目录
//参数
// Dir ,输入的目录字符串
// bIsRecursion ,是否递归
// true 是, false 不是.
GetFileDataStream( Dir, true ); //查看目录是否存在数据流
ULONG DirStrLen = 0;
while( *(Dir+DirStrLen) ) DirStrLen++; //计算目录字符串长度
DirStrLen--;
if( DirStrLen+4 > (ULONG)MAX_PATH ) //目录字符串过长
{
printf( "输入的目录太长!/n" );
return ;
}
if( *(Dir+DirStrLen) == '//' ) //在字符串最后添加"/*.*"
{
*(Dir+DirStrLen) = '/0'; //去掉斜线
}
char* Path = (char*)malloc( MAX_PATH + 1 ); //申请内存
memset( Path, 0, MAX_PATH + 1 );
memcpy( Path, Dir, MAX_PATH );
strcat( Path, "//*.*" ); //查找当前目录下的*.*文件(即所有文件)
//这里查打此目录下的所有文件
HANDLE hFile;
WIN32_FIND_DATA FindFile;
//开始查找文件夹下的所有文件及目录
hFile = FindFirstFile( Path, &FindFile );
if( hFile != INVALID_HANDLE_VALUE ) //存在文件或目录
{
do
{
if ( !( FindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) /
&& ( strcmp( FindFile.cFileName, "." ) != 0 ) /
&& ( strcmp( FindFile.cFileName, ".." ) != 0 ) ) //不是目录,即文件
{
char Path2[MAX_PATH+1];
sprintf( Path2, "%s//%s", Dir, FindFile.cFileName );
// printf( "F ~~~ %s/n", Path2 );///////////查看文件
GetFileDataStream( Path2, false ); //查看该文件是否存在数据流
}
else if( strcmp( FindFile.cFileName, "." ) != 0 /
&& strcmp( FindFile.cFileName, ".." ) != 0 ) //下一级目录
{
//查看子目录中是否有数据流,并且递归查询该目录中的文件(如果有要求)
char Path2[MAX_PATH+1];
sprintf( Path2, "%s//%s", Dir, FindFile.cFileName );
// printf( "D ~~~ %s/n", Path2 );///////////查看目录
if( bIsRecursion ) //如果需要递归
{
FindAllFilesInDirectory( Path2, true ); //递归
}
else //不递归,只查看该子目录
{
GetFileDataStream( Path2, true ); //查看该目录是否有数据流
}
}
} while( FindNextFile( hFile, &FindFile ) ); //还有文件或目录
}
free( Path ); //释放内存
}
void Usage() //用法帮助
{
printf( " DataStreamFinder/n/n" );
printf( " Made By Adly/n" );
printf( " 2007-10-10/n" );
printf( " QQ: 369046978/n" );
printf( " Email: adly369046978@163.com/n/n" );
printf( "It Can Scan NTFS Data Stream!/n" );
printf( "Usage:/n" );
printf( " DSF [-F File | [-S] Directory ]/n/n" );
printf( " -F Check a File/n" );
printf( " -S Recursion Scan Directory And SubDirectory/n/n" );
printf( " Example:/n" );
printf( " DSF -F C://boot.ini Scan /"C://boot.ini/" File/n" );
printf( " DSF C:// Scan /"C:///" Directory's File And/n" );
printf( " SubDirectory But Recursion/n" );
printf( " DSF -S C:// Scan /"C:///" Directory's File And/n" );
printf( " All SubDirectory (Recursion)/n" );
}
void main( int argc, char* argv[] )
{
try{
if( argc != 2 && argc != 3 )
{
Usage(); //帮助函数
return ;
}
if( argc == 2 ) //扫描不递归的目录
{
if( strcmp( argv[1], "/?" ) == 0 )
{
Usage();
}
else
{
FindAllFilesInDirectory( argv[1], false );
}
}
else //加了两个参数来运行
{
if( ( argv[1][0] == '-' ) && ( argv[1][2] == '/0' ) ) //第一个参数的第一个字符为参数号
{
switch( argv[1][1] )
{
case 'f': //文件扫描
case 'F':
GetFileDataStream( argv[2], false );
break;
case 's': //带递归的目录扫描
case 'S':
FindAllFilesInDirectory( argv[2], true );
break;
default:
Usage();
}
}
else if( ( argv[2][0] == '-' ) && ( argv[2][2] == '/0' ) ) //第二个参数的第一个字符为参数号
{
switch( argv[2][1] )
{
case 'f': //文件扫描
case 'F':
GetFileDataStream( argv[1], false );
break;
case 's': //带递归的目录扫描
case 'S':
FindAllFilesInDirectory( argv[1], true );
break;
default:
Usage();
}
}
else //错误的参数
{
Usage(); //帮助函数
}
}
}
catch(...)
{
printf( "/n程序发生异常!/n" );
}
}