 Use this Code :
Streams.h
typedef INT NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
typedef struct _IO_STATUS_BLOCK {
NTSTATUS Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef VOID (*PIO_APC_ROUTINE) (
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileObjectIdInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileAttributeTagInformation,
FileTrackingInformation,
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
#pragma pack(4)
typedef struct {
ULONG NextEntry;
ULONG NameLength;
LARGE_INTEGER Size;
LARGE_INTEGER AllocationSize;
USHORT Name[1];
} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
#pragma pack()
Streams.c
#define UNICODE 1
#include <windows.h>
#include <stdio.h>
#include "streams.h"
NTSTATUS (__stdcall *NtQueryInformationFile)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
ULONG (__stdcall *RtlNtStatusToDosError) (
IN NTSTATUS Status
);
ULONG FilesWithStreams = 0;
ULONG FilesProcessed = 0;
ULONG DotsPrinted = 0;
BOOLEAN PrintDirectoryOpenErrors = FALSE;
void PrintNtError( NTSTATUS status )
{
WCHAR *errMsg;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, RtlNtStatusToDosError( status ),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &errMsg, 0, NULL );
wprintf(L"%s\n", errMsg );
LocalFree( errMsg );
}
void PrintWin32Error( DWORD ErrorCode )
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL );
wprintf(L"%s\n", lpMsgBuf );
LocalFree( lpMsgBuf );
}
BOOL EnableTokenPrivilege( PTCHAR PrivilegeName )
{
TOKEN_PRIVILEGES tp;
LUID luid;
HANDLE hToken;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
if(!OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken )) {
return FALSE;
}
if(!LookupPrivilegeValue( NULL, PrivilegeName, &luid )) return FALSE;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);
return GetLastError() == ERROR_SUCCESS;
}
VOID ProcessFile( WCHAR *FileName, BOOLEAN IsDirectory, BOOLEAN Delete )
{
PFILE_STREAM_INFORMATION streamInfo, streamInfoPtr;
ULONG streamInfoSize = 0;
BOOLEAN printedFile = FALSE;
NTSTATUS status;
HANDLE fileHandle;
WCHAR streamName[MAX_PATH];
WCHAR fullStreamName[MAX_PATH];
IO_STATUS_BLOCK ioStatus;
fileHandle = CreateFile( FileName, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, 0 );
if( fileHandle == INVALID_HANDLE_VALUE ) {
if( !IsDirectory || PrintDirectoryOpenErrors ) {
wprintf(L"\rError opening %s:\n", FileName );
PrintWin32Error( GetLastError() );
}
return;
}
if( !(++FilesProcessed % 500)) {
if( DotsPrinted == 3 ) {
wprintf(L"\r \r");
DotsPrinted = 0;
} else {
DotsPrinted++;
wprintf(L".");
}
fflush( stdout );
}
streamInfoSize = 16384;
streamInfo = malloc( streamInfoSize );
status = STATUS_BUFFER_OVERFLOW;
while( status == STATUS_BUFFER_OVERFLOW ) {
status = NtQueryInformationFile( fileHandle, &ioStatus,
streamInfo, streamInfoSize,
FileStreamInformation );
if( status == STATUS_BUFFER_OVERFLOW ) {
free( streamInfo );
streamInfoSize += 16384;
streamInfo = malloc( streamInfoSize );
} else {
break;
}
}
if( NT_SUCCESS( status ) && ioStatus.Information ) {
streamInfoPtr = streamInfo;
while( 1 ) {
memcpy( streamName,
streamInfoPtr->Name,
streamInfoPtr->NameLength );
streamName[ streamInfoPtr->NameLength/2 ] = 0;
if( wcsicmp( streamName, L"::$DATA" )) {
if( !printedFile ) {
wprintf(L"\r%s:\n", FileName );
printedFile = TRUE;
}
if( Delete ) {
swprintf( fullStreamName, L"%s%s", FileName, streamName );
if( !DeleteFile( fullStreamName )) {
wprintf(L" Error deleting %s:\n", streamName );
PrintWin32Error( GetLastError());
} else {
wprintf(L" Deleted %s\n", streamName );
}
} else {
wprintf(L" %20s\t%I64d\n", streamName, streamInfoPtr->Size.QuadPart );
}
}
if( !streamInfoPtr->NextEntry ) break;
FilesWithStreams++;
streamInfoPtr = (PFILE_STREAM_INFORMATION) ((char *) streamInfoPtr +
streamInfoPtr->NextEntry );
}
} else if( !NT_SUCCESS( status )) {
wprintf(L"\rError on %s: ", FileName );
PrintNtError( status );
}
free( streamInfo );
CloseHandle( fileHandle );
}
void ProcessDirectory( WCHAR *PathName, WCHAR *SearchPattern,
BOOLEAN Recurse, BOOLEAN Delete )
{
WCHAR subName[MAX_PATH], fileSearchName[MAX_PATH], searchName[MAX_PATH];
HANDLE dirHandle, patternHandle;
static BOOLEAN firstCall = TRUE;
WIN32_FIND_DATA foundFile;
if( firstCall ) {
if( PathName[ wcslen( PathName ) - 1] == L'\\' ) {
PathName[ wcslen( PathName ) - 1] = 0;
}
if( wcsrchr( PathName, '*' ) ) {
if( wcsrchr( PathName, '\\' ) ) {
swprintf( SearchPattern, wcsrchr( PathName, '\\' )+1 );
wcscpy( searchName, PathName );
wcscpy( wcsrchr( searchName, '\\')+1, L"*.*" );
} else {
swprintf( SearchPattern, PathName );
wcscpy( searchName, PathName );
}
swprintf( fileSearchName, L"%s", PathName );
} else {
swprintf( SearchPattern, L"*.*" );
if( Recurse ) {
swprintf( searchName, L"%s\\*.*", PathName );
swprintf( fileSearchName, L"%s\\*.*", PathName );
} else {
swprintf( searchName, L"%s", PathName );
swprintf( fileSearchName, L"%s", PathName );
}
}
} else {
swprintf( searchName, L"%s\\*.*", PathName );
swprintf( fileSearchName, L"%s\\%s", PathName, SearchPattern );
}
if( (patternHandle = FindFirstFile( fileSearchName, &foundFile )) !=
INVALID_HANDLE_VALUE ) {
do {
if( firstCall || (wcscmp( foundFile.cFileName, L"." ) &&
wcscmp( foundFile.cFileName, L".." ))) {
wcscpy( subName, searchName );
if( wcsrchr( subName, '\\' ) )
wcscpy( wcsrchr( subName, '\\')+1, foundFile.cFileName );
else
wcscpy( subName, foundFile.cFileName );
ProcessFile( subName,
(BOOLEAN) (foundFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY),
Delete );
}
} while( FindNextFile( patternHandle, &foundFile ));
FindClose( patternHandle );
}
if( Recurse ) {
if( firstCall && !wcsrchr( searchName, L'\\') ) {
if( wcsrchr( searchName, L'*' )) {
if( (dirHandle = FindFirstFile( L"*.*", &foundFile )) ==
INVALID_HANDLE_VALUE ) {
return;
}
} else {
if( (dirHandle = FindFirstFile( searchName, &foundFile )) ==
INVALID_HANDLE_VALUE ) {
return;
}
}
} else {
if( (dirHandle = FindFirstFile( searchName, &foundFile )) ==
INVALID_HANDLE_VALUE ) {
return;
}
}
firstCall = FALSE;
do {
if( (foundFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
wcscmp( foundFile.cFileName, L"." ) &&
wcscmp( foundFile.cFileName, L".." )) {
wcscpy( subName, searchName );
if( wcsrchr( subName, '\\' ) )
wcscpy( wcsrchr( subName, '\\')+1, foundFile.cFileName );
else
wcscpy( subName, foundFile.cFileName );
ProcessDirectory( subName, SearchPattern, Recurse, Delete );
}
} while( FindNextFile( dirHandle, &foundFile ));
}
FindClose( dirHandle );
}
int Usage( WCHAR *ProgramName )
{
wprintf(L"usage: %s [-s] [-d] <file or directory>\n", ProgramName );
wprintf(L"-s Recurse subdirectories\n");
wprintf(L"-d Delete streams\n\n");
return -1;
}
int wmain( int argc, WCHAR *argv[] )
{
BOOLEAN recurse = FALSE, delete = FALSE;
PWCHAR filePart;
WCHAR volume[] = L"C:\\";
DWORD fsFlags;
WCHAR searchPattern[MAX_PATH];
WCHAR searchPath[MAX_PATH];
int i;
if( argc > 1 ) {
for( i = 1; i < argc; i++ ) {
if( argv[i][0] != L'/' && argv[i][0] != L'-' ) {
if( i != argc-1 ) {
wprintf( argv[i] );
return Usage( argv[0] );
}
continue;
}
if( argv[i][1] == L's' || argv[i][1] == L'S' ) {
recurse = TRUE;
} else if( argv[i][1] == L'd' || argv[i][1] == 'D' ) {
delete = TRUE;
} else return Usage( argv[0] );
}
} else {
return Usage( argv[0] );
}
if( EnableTokenPrivilege( SE_BACKUP_NAME )) {
PrintDirectoryOpenErrors = TRUE;
}
if( !(NtQueryInformationFile = (void *) GetProcAddress( GetModuleHandle(L"ntdll.dll"),
"NtQueryInformationFile" )) ) {
wprintf(L"\nCould not find NtQueryInformationFile entry point in NTDLL.DLL\n");
exit(1);
}
if( !(RtlNtStatusToDosError = (void *) GetProcAddress( GetModuleHandle(L"ntdll.dll"),
"RtlNtStatusToDosError" )) ) {
wprintf(L"\nCould not find RtlNtStatusToDosError entry point in NTDLL.DLL\n");
exit(1);
}
GetFullPathName( argv[argc-1], MAX_PATH, searchPath, &filePart );
if( searchPath[1] == L':' ) {
fsFlags = 0;
volume[0] = searchPath[0];
GetVolumeInformation( volume, NULL, 0, NULL, NULL, &fsFlags, NULL, 0 );
if( !(fsFlags & FILE_NAMED_STREAMS )) {
wprintf(L"\nThe specified volume does not support streams.\n\n");
exit(2);
}
}
ProcessDirectory( searchPath, searchPattern, recurse, delete );
if( !FilesWithStreams ) wprintf(L"No files with streams found.\n\n");
return 0;
}
|