System Delphi

Title: NTFS Alternate Data Streams Dir Listing
Question: In article 4143 Milad Efterkharian demonstrates the operation of W2K/XP NTFS "Alternate Data Streams". In essence it is possible to hide data in ADS by methods such as
Memo1.Lines.SaveToFile('c:\temp\MyFile.Txt:MyHide');
and Retrieve such data as
Memo1.Lines.LoadFrom('c:\temp\MyFile.txt:MyHide');
This is fine as long as you know the name of the ADS. There are not many tools that will list these hidden ADS files, even Windows Explorer does not list them. This function will list ADS file names of a given file in a string list. The objects property of the list contains the file size.
eg.
GetFileADSNames('c:\temp\MyFile.txt',Listbox1.Items);
... c:\temp\myfile,txt:mike
... c:\temp\myfile.txt:gary
... etc.
iFileSize : integer;
for i := 0 to Listbox1.Items.Count - 1 do begin
iFileSize := integer(Listbox1.Items.Objects[i]);
.....
.....
end;
Search the web for "Alternate Data Streams" for more information on this topic.
Answer:
uses Windows;
// ===============================================================
// Load a string list with ADS (Alternate Data Stream) names
// the integer(AList.Object[?]) contains the File Size
// ===============================================================
procedure GetFileADSNames(const AFileName : string; AList : TStrings);
var hHandle : THandle;
sName : string;
iNumRead,iLo,iHi : DWORD;
pCtx : pointer;
pBuffer,pBytePtr : PByte;
pWsi : PWin32StreamID absolute pBuffer;
wszStreamName: array[0..MAX_PATH] of widechar;
begin
AList.BeginUpdate;
AList.Clear;
GetMem(pBuffer,4096);
pCtx := nil;
hHandle := CreateFile(PChar(AFileName),GENERIC_READ,0,nil,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,0);
if (hHandle INVALID_HANDLE_VALUE) then begin
while true do begin
// We are at the start of a stream header. read it.
pBytePtr := pBuffer;
if BackupRead(hHandle,pBytePtr,20,iNumRead,
false,true,pCtx) then begin
if iNumRead = 0 then
break
else begin
// Can we get a stream name ?
sName := '';
if pWsi.dwStreamNameSize 0 then begin
FillChar(wszStreamName,SizeOf(wszStreamName),0);
if BackupRead(hHandle,@(wszStreamName[0]),pWsi.dwStreamNameSize,
iNumRead,false,true,pCtx) then begin
if iNumRead pWsi.dwStreamNameSize then
break
else begin
// Yep, have a name, convert from WideChar
sName := WideCharToString(wszStreamName);
// Clean up Name
if sName '' then begin
sName := copy(sName,2,length(sName));
sName := ':' + copy(sName,1,pos(':',sName) - 1);
end;
AList.AddObject(AFileName + sName,TObject(pWsi.Size));
end;
end
else
break;
end;
// Skip to start of next stream data
if pWsi.Size 0 then
BackupSeek(hHandle,high(DWORD),high(DWORD),iLo,iHi,@pCtx);
end;
end
else
break;
end;
// Release the context
BackupRead(hHandle,pBuffer,0,iNumRead,true,false,pCtx);
CloseHandle(hHandle);
end;
FreeMem(pBuffer);
AList.EndUpdate;
end;