Учимся работать с "многопоточными файлами" в NT
Материал из DRKB
Учимся работать с "многопоточными файлами" в NT[править | править код]
1. Создание(изменение) и чтение "Опциональных потоков"[править | править код]
procedure TForm1.Button1Click(Sender: TObject);
begin
// сохраняем то что в Memo в "многопоточный файл"
Memo1.Lines.SaveToFile('k:\memo.txt');
Memo2.Lines.SaveToFile('k:\memo.txt:memo2'); // опциональный поток
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// читаем в обратном порядке из "многопоточного файла"
Memo1.Lines.LoadFromFile('k:\memo.txt:memo2'); // опциональный поток
Memo2.Lines.LoadFromFile('k:\memo.txt');
end;
Как видно из первого примера... что бы прочитать "Опциональный поток" нам необходимо знать его "имя"... . Если вам не известно енто "имя", а очень хочется... тогда код 2 пункта предназначен для вас
2. Определяем инфу о файле/директории - читаем инфу о потоках:[править | править код]
function InfoFileStreams(const FileName: string; Delete: Boolean; out RStreams: string): Boolean;
{ Входные данные:
- FileName: Имя файла/дирректории.
- Delete: Если Truе то... по мимо инфы еще и удаляем "Опциональные потоки" файла.
Выходные данные:
- True: Что-то смоглы определить :)
- RStreams - Определенная инфа}
const
Error_Buffer_Overflow = $80000005;
type
_IO_STATUS_BLOCK = packed record
Status: DWord;
Information: DWord;
end;
FILE_STREAM_INFORMATION = packed record
NextEntry: DWord;
NameLength: DWord;
Size: Int64;
AllocationSize: Int64;
Name: WideChar;
end;
_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);
var
NtQueryInformationFile: function (FileHandle: DWord; out IoStatusBlock: _IO_STATUS_BLOCK;
FileInformation: Pointer; Length: DWord; FileInformationClass: _FILE_INFORMATION_CLASS): DWord; stdcall;
fHandle: DWord;
StreamIS: DWord;
StreamInfo, tSI: ^FILE_STREAM_INFORMATION;
IoSB: _IO_STATUS_BLOCK;
t: DWord;
sN, sT: string;
NextEntry, sM: Boolean;
begin
Result := False;
NtQueryInformationFile := GetProcAddress(GetModuleHandle('ntdll.dll'), 'NtQueryInformationFile');
if Assigned(NtQueryInformationFile) = False then exit;
fHandle := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if fHandle <> INVALID_HANDLE_VALUE then
begin
StreamIS := 0;
GetMem(StreamInfo, StreamIS);
repeat
FreeMem(StreamInfo, StreamIS);
StreamIS := StreamIS + 16384;
GetMem(StreamInfo, StreamIS);
t := NtQueryInformationFile(fHandle, IoSB, StreamInfo, StreamIS, FileStreamInformation);
until (t <> Error_Buffer_Overflow);
if (t = 0) and (IoSB.Information <> 0) then
begin
tSI := StreamInfo;
sN := '';
NextEntry := True;
Result := True;
sM := False;
while NextEntry do
begin
if tSI^.NextEntry = 0 then NextEntry := False;
sT := Copy(PWideChar(@tSI^.Name), 0, tSI^.NameLength div SizeOf(WideChar));
if (sM = False) and (AnsiCompareText(sT, '::$DATA') = 0) then
begin
sM := True;
sN := sN + 'Основной поток: ' + sT + '; Размер: ' + IntToStr(tSI^.Size) + ' байт' + Chr($D) + Chr($A);
end
else
begin
sN := sN + 'Опциональный поток: ' + sT + '; Размер: ' + IntToStr(tSI^.Size) + ' байт' + Chr($D) + Chr($A);
if Delete then
if DeleteFile(FileName+sT) then
sN := sN + 'Удален!' + Chr($D) + Chr($A);
end;
tSI := Pointer(DWord(tSI) + tSI^.NextEntry);
end;
RStreams := sN;
end;
FreeMem(StreamInfo, StreamIS);
CloseHandle(fHandle);
end;
end;
Ну и до кучи... пример использывания InfoFileStreams:
const
SE_BACKUP_NAME = 'SeBackupPrivilege';
function NTSetPrivilege(sPrivilege: string; fEnabled: LongBool): Boolean;
var
hToken: THandle;
TokenPriv, PrevTokenPriv: TOKEN_PRIVILEGES;
PrivSet: PRIVILEGE_SET;
f: LongBool;
i: Cardinal;
begin
Result := False;
if Win32Platform <> VER_PLATFORM_WIN32_NT then exit;
PrivSet.PrivilegeCount := 1;
PrivSet.Control := 0;
PrivSet.Privilege[0].Attributes := 0;
if LookupPrivilegeValue(nil, PChar(sPrivilege), PrivSet.Privilege[0].Luid) then
begin
if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
begin
try
if PrivilegeCheck(hToken, PrivSet, f) and (f <> fEnabled) then
begin
if LookupPrivilegeValue(nil, PChar(sPrivilege), TokenPriv.Privileges[0].Luid) then
begin
TokenPriv.PrivilegeCount := 1;
if fEnabled then
TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
TokenPriv.Privileges[0].Attributes := 0;
i := 0;
PrevTokenPriv := TokenPriv;
AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv), PrevTokenPriv, i);
Result := (GetLastError = ERROR_SUCCESS);
end;
end;
except
end;
CloseHandle(hToken);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
NTSetPrivilege(SE_BACKUP_NAME, True);
if InfoFileStreams('k:\memo.txt', False, s) then Memo1.Lines.Text := s;
// Удаляем опциональные потоки
//if InfoFileStreams('k:\memo.txt', True, s) then Memo1.Lines.Text := s;
end;
Author: Girder
Source: Взято с Vingrad.ru http://forum.vingrad.ru
ID: 03121