#! c:\perl\bin\perl.exe # Modified from "Win32 Perl Scripting: Administrators Handbook" by Dave Roth use Win32::API::Prototype; my $OPEN_EXISTING = 3; my $GENERIC_READ = 0x80000000; my $BACKUP_DATA = 0x00000001; my $BACKUP_ALTERNATE_DATA = 0x00000004; my $FILE_SHARE_READ = 0x00000001; my $FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; ApiLink( 'kernel32.dll', 'HANDLE CreateFile( LPCTSTR pszPath, DWORD dwAccess, DWORD dwShareMode, PVOID SecurityAttributes, DWORD dwCreationDist, DWORD dwFlags, HANDLE hTemplate )' ) || die "Can not locate CreateFile()"; ApiLink( 'kernel32.dll', 'BOOL CloseHandle( HANDLE hFile )' ) || die "Can not locate CloseHandle()"; ApiLink( 'kernel32.dll', 'BOOL BackupRead( HANDLE hFile, LPBYTE pBuffer, DWORD dwBytesToRead, LPDWORD pdwBytesRead, BOOL bAbort, BOOL bProcessSecurity, LPVOID *ppContext)' ) || die "Can not locate BackupRead()"; ApiLink( 'kernel32.dll', 'BOOL BackupSeek( HANDLE hFile, DWORD dwLowBytesToSeek, DWORD dwHighBytesToSeek, LPDWORD pdwLowByteSeeked, LPDWORD pdwHighByteSeeked, LPVOID *pContext )' ) || die "Can not create BackupSeek()"; # Mods by H. Carvey my $dir = shift || die "You must enter a directory\n"; $dir = $dir."\\" unless ($dir =~ m/\\$/); opendir(DIR,$dir); my @Files = readdir(DIR); close(DIR); foreach my $File (@Files) { next if ($File eq ".."); $File = $dir.$File; $hFile = CreateFile( $File, $GENERIC_READ, $FILE_SHARE_READ, undef, $OPEN_EXISTING, $FILE_FLAG_BACKUP_SEMANTICS, 0 ) || die "Can not open the file '$File'\n"; # If CreateFile() failed $hFile is a negative value if($hFile > 0) { my $iStreamCount = 0; my $pBytesRead = pack( "L", 0 ); my $pContext = pack( "L", 0 ); my $pStreamIDStruct = pack( "L5", 0,0,0,0,0,0 ); while( BackupRead( $hFile, $pStreamIDStruct, length($pStreamIDStruct), $pBytesRead, 0, 0, $pContext)) { my $BytesRead = unpack("L",$pBytesRead); my $Context = unpack("L",$pContext); my %Stream; my($pSeekBytesLow,$pSeekBytesHigh) = (pack("L",0),pack("L",0)); my $StreamName = ""; my $StreamSize; # No more data to read last if($BytesRead == 0); @Stream{ id, attributes, size_low, size_high, name_size } = unpack("L5",$pStreamIDStruct); # This indicates that an ADS has been detected. if($BACKUP_ALTERNATE_DATA == $Stream{id}) { $StreamName = NewString($Stream{name_size}); if( BackupRead( $hFile, $StreamName, $Stream{name_size}, $pBytesRead, 0, 0, $pContext)) { my $String = CleanString($StreamName,1); $String =~ s/^:(.*?):.*$/$1/; $StreamName = ":".$String; } my $FileName; if (-d $File) { if ($File =~ m/\.$/) { $FileName = substr($File,0,length($File)-1); } elsif (!($File =~ m/\\$/)) { $FileName = $File."\\"; } } elsif (-f $File) { $FileName = $File; } $StreamSize = MakeLargeInt($Stream{size_low},$Stream{size_high}); print "$FileName$StreamName\t($StreamSize bytes) \n" if($StreamName ne ""); print "\n"; } # elsif($BACKUP_DATA == $Stream{id}) { # $StreamName = "
"; # } # printf( " % 3d) %s (%s bytes)\n", # ++$iStreamCount, # $StreamName, # FormatNumber($StreamSize)) if($StreamName ne ""); # Move to next stream... last if(!BackupSeek($hFile, $Stream{size_low}, $Stream{size_high}, $pSeekBytesLow, $pSeekBytesHigh, $pContext)); $pBytesRead = pack("L2",0); $pStreamIDStruct = pack("L5",0,0,0,0,0); } # Abort the backup reading. Win32 API claims we MUST do this. BackupRead( $hFile,undef,0,0,1,0,$pContext ); CloseHandle( $hFile ); } } sub FormatNumber { my( $Num ) = @_; {} while( $Num =~ s/^(-?\d+)(\d{3})/$1,$2/ ); return( $Num ); } sub MakeLargeInt { my( $Low, $High ) = @_; return( $High * ( 1 + 0xFFFFFFFF ) + $Low ); }