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

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" );
 }
}

posted on 2009-08-26 13:38  Yincheng  阅读(247)  评论(0编辑  收藏  举报