| 
| 
 | Вопрос # 944/ вопрос открыт / | 
 |  Здравствуйте, эксперты! Подскажите пожалуйста, как можно определить, что началось копирование или перемещение данных в Windows? Можно ли определить что, откуда и куда копируется или перемещается? 
|  |   Вопрос задал: alone (статус: Посетитель)Вопрос отправлен: 28 сентября 2007, 23:02
 Состояние вопроса: открыт, ответов: 2.
 |  Ответ #1. Отвечает эксперт: Грег Леонов Доброе утро, Олег!
 Тут однозначно нужно использовать WinAPI.
 А вообще считаю что отследить "все" записи в Windows - ресурсоемкая операция. Т.к. Windows постоянно что-то пишет на диск(правда постоянно новые файлы не создает).
 
 http://download.sysinternals.com/Files/Filemon.zip - прога чтоб отследить все операции с файловой системой в ОС.
 
 Я сам в WinAPI не очень хорошо разбираюсь, но поюзав google, нашел код реализации поиска изменений в файловой системе с помощью WinAPI.
 Приложение:Переключить в обычный режим program file_seeker; {$APPTYPE CONSOLE} uses  SysUtils, windows, tintlist; type  NTStatus = cardinal;  PVOID    = pointer;  USHORT = WORD;  UCHAR = byte;  PWSTR = PWideChar;    STATUS_SUCCESS              = NTStatus($00000000);  STATUS_ACCESS_DENIED        = NTStatus($C0000022);  STATUS_INFO_LENGTH_MISMATCH = NTStatus($C0000004);  SEVERITY_ERROR              = NTStatus($C0000000); const SystemHandleInformation              	=	16;      OB_TYPE_FILE                          = 28;   typePClientID = ^TClientID;TClientID = packed record UniqueProcess:cardinal; UniqueThread:cardinal;end; PUnicodeString = ^TUnicodeString;  TUnicodeString = packed record    Length: Word;    MaximumLength: Word;    Buffer: PWideChar;end; PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;SYSTEM_HANDLE_INFORMATION = packed record   ProcessId: dword;   ObjectTypeNumber: byte;   Flags: byte;   Handle: word;   pObject: pointer;   GrantedAccess: dword;   end; PSYSTEM_HANDLE_INFORMATION_EX = ^SYSTEM_HANDLE_INFORMATION_EX;SYSTEM_HANDLE_INFORMATION_EX = packed record   NumberOfHandles: dword;   Information: array [0..0] of SYSTEM_HANDLE_INFORMATION;   end; Function ZwQuerySystemInformation(ASystemInformationClass: dword;                                  ASystemInformation: Pointer;                                  ASystemInformationLength: dword;                                  AReturnLength:PCardinal): NTStatus;                                  stdcall;external 'ntdll.dll';  function EnablePrivilegeEx(Process: dword; lpPrivilegeName: PChar):Boolean;var  hToken: dword;  NameValue: Int64;  tkp: TOKEN_PRIVILEGES;  ReturnLength: dword;begin  Result:=false;   OpenProcessToken(Process, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);   if not LookupPrivilegeValue(nil, lpPrivilegeName, NameValue) then    begin     CloseHandle(hToken);     exit;    end;  tkp.PrivilegeCount := 1;  tkp.Privileges[0].Luid := NameValue;  tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;   AdjustTokenPrivileges(hToken, false, tkp, SizeOf(TOKEN_PRIVILEGES), tkp, ReturnLength);  if GetLastError() <> ERROR_SUCCESS then     begin      CloseHandle(hToken);      exit;     end;  Result:=true;  CloseHandle(hToken);end;  function EnablePrivilege(lpPrivilegeName: PChar):Boolean;begin  Result := EnablePrivilegeEx(INVALID_HANDLE_VALUE, lpPrivilegeName);end;   function EnableDebugPrivilegeEx(Process: dword):Boolean;begin  Result := EnablePrivilegeEx(Process, 'SeDebugPrivilege');end;  function EnableDebugPrivilege():Boolean;begin  Result := EnablePrivilegeEx(INVALID_HANDLE_VALUE, 'SeDebugPrivilege');end;  Function GetInfoTable(ATableType:dword):Pointer;var mSize: dword; mPtr: pointer; St: NTStatus;begin Result := nil;  repeat   mPtr := VirtualAlloc(nil, mSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);   if mPtr = nil then Exit;   St := ZwQuerySystemInformation(ATableType, mPtr, mSize, nil);   if St = STATUS_INFO_LENGTH_MISMATCH then         VirtualFree(mPtr, 0, MEM_RELEASE);        mSize := mSize * 2;      end; until St <> STATUS_INFO_LENGTH_MISMATCH; if St = STATUS_SUCCESS   then Result := mPtr   else VirtualFree(mPtr, 0, MEM_RELEASE);end; var HandlesInfo: PSYSTEM_HANDLE_INFORMATION_EX; r: integer; hProcess, tHandle: dword; file_h: tintegerlist;begin   file_h := tintegerlist.Create;   EnableDebugPrivilege(); HandlesInfo := GetInfoTable(SystemHandleInformation); for r := 0 to HandlesInfo^.NumberOfHandles do   if HandlesInfo^.Information[r].ObjectTypeNumber = OB_TYPE_FILE then    begin      file_h.Add(HandlesInfo^.Information[r].Handle);    end;  VirtualFree(HandlesInfo, 0, MEM_RELEASE);    while true do  begin    Sleep(200);      HandlesInfo := GetInfoTable(SystemHandleInformation);   for r := 0 to HandlesInfo^.NumberOfHandles do     if HandlesInfo^.Information[r].ObjectTypeNumber = OB_TYPE_FILE then      begin        if file_h.IndexOf(HandlesInfo^.Information[r].Handle)=-1 then          begin            file_h.Add(HandlesInfo^.Information[r].Handle);            writeln(HandlesInfo^.Information[r].Handle, ' - added a file handle');          end;      end;     VirtualFree(HandlesInfo, 0, MEM_RELEASE);  end;  readln; end.  
|  | Ответ отправил: Грег Леонов (статус: 1-ый класс)Время отправки: 29 сентября 2007, 00:47
 Оценка за ответ: 4
 |  Ответ #2. Отвечает эксперт: Feniks Здравствуйте, Гадлевский Олег Вячеславович!Сам я не пробовал, но пару примеров нашел. См. в приложении.
 Приложение:Переключить в обычный режим   unit Unit1; {cDrkb v.3(2007): www.drkb.ru} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; type PFileNotifyInformation = ^TFileNotifyInformation;TFileNotifyInformation = record   NextEntryOffset: DWORD;   Action: DWORD;   FileNameLength: DWORD;   FileName: array [0..MAX_PATH - 1] of WideChar;end; TForm1 = class(TForm)   Memo1: TMemo;   procedure FormCreate(Sender: TObject);end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject);constFilter =  FILE_NOTIFY_CHANGE_FILE_NAME or           FILE_NOTIFY_CHANGE_DIR_NAME or           FILE_NOTIFY_CHANGE_ATTRIBUTES or           FILE_NOTIFY_CHANGE_SIZE or           FILE_NOTIFY_CHANGE_LAST_WRITE or           FILE_NOTIFY_CHANGE_LAST_ACCESS or           FILE_NOTIFY_CHANGE_CREATION or           FILE_NOTIFY_CHANGE_SECURITY;var Dir: THandle;Notify: TFileNotifyInformation;BytesReturned: DWORD; begin   Dir := CreateFile('d:', GENERIC_READ,   FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,   nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);if Dir <> INVALID_HANDLE_VALUE thentry   if not ReadDirectoryChangesW(Dir, @Notify, SizeOf(TFileNotifyInformation),     False, Filter, @BytesReturned, nil, nil) then     raise Exception.Create(SysErrorMessage(GetLastError))   else     case Notify.Action of       FILE_ACTION_ADDED: ShowMessage('New file' + Notify.FileName);       FILE_ACTION_REMOVED: ShowMessage('Delete file' + Notify.FileName);       FILE_ACTION_MODIFIED: ShowMessage('Modify file' + Notify.FileName);       FILE_ACTION_RENAMED_OLD_NAME: ShowMessage('Old Name file' + Notify.FileName);       FILE_ACTION_RENAMED_NEW_NAME: ShowMessage('New Name file' + Notify.FileName);     end;finally   CloseHandle(Dir);end;end;end. ====================================================   unit wfsU; interface type   PInfoCallback = ^TInfoCallback;TInfoCallback = record    end;   TWatchFileSystemCallback = procedure (pInfo: TInfoCallback);       procedure StartWatch(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallback:
TWatchFileSystemCallback);   procedure StopWatch; implementation uses Classes, Windows, SysUtils; const FILE_LIST_DIRECTORY   = $0001; type PFileNotifyInformation = ^TFileNotifyInformation;TFileNotifyInformation = record   NextEntryOffset : DWORD;   Action          : DWORD;   FileNameLength  : DWORD;   FileName        : array[0..0] of WideChar;end; WFSError = class(Exception); TWFS = class(TThread)private   FName           : string;   FFilter         : Cardinal;   FSubTree        : boolean;   FInfoCallback   : TWatchFileSystemCallback;   FWatchHandle    : THandle;   FWatchBuf       : array[0..4096] of Byte;   FOverLapp       : TOverlapped;   FPOverLapp      : POverlapped;   FBytesWritte    : DWORD;   FCompletionPort : THandle;   FNumBytes       : Cardinal;   FOldFileName    : string;   function CreateDirHandle(aDir: string): THandle;   procedure WatchEvent;   procedure HandleEvent;protected   procedure Execute; override;public   constructor Create(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallback:
TWatchFileSystemCallback);   destructor Destroy; override;end;  var WFS : TWFS; procedure StartWatch(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallback:
TWatchFileSystemCallback);beginWFS:=TWFS.Create(pName, pFilter, pSubTree, pInfoCallback);end; procedure StopWatch;varTemp : TWFS;beginif Assigned(WFS) thenbegin  PostQueuedCompletionStatus(WFS.FCompletionPort, 0, 0, nil);  Temp := WFS;  WFS:=nil;  Temp.Terminate;end;end; constructor TWFS.Create(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallback:
TWatchFileSystemCallback);begininherited Create(True);FreeOnTerminate:=True;FName:=IncludeTrailingBackslash(pName);FFilter:=pFilter;FSubTree:=pSubTree;FOldFileName:=EmptyStr;ZeroMemory(@FOverLapp, SizeOf(TOverLapped));FPOverLapp:=@FOverLapp;ZeroMemory(@FWatchBuf, SizeOf(FWatchBuf));FInfoCallback:=pInfoCallback;Resumeend; destructor TWFS.Destroy;beginPostQueuedCompletionStatus(FCompletionPort, 0, 0, nil);CloseHandle(FWatchHandle);FWatchHandle:=0;CloseHandle(FCompletionPort);FCompletionPort:=0;inherited Destroy;end; function TWFS.CreateDirHandle(aDir: string): THandle;beginResult:=CreateFile(PChar(aDir), FILE_LIST_DIRECTORY,
FILE_SHARE_READ+FILE_SHARE_DELETE+FILE_SHARE_WRITE,                  nil,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED, 0);end; procedure TWFS.Execute;beginFWatchHandle:=CreateDirHandle(FName);WatchEvent;end; procedure TWFS.HandleEvent;varFileNotifyInfo : PFileNotifyInformation;InfoCallback   : TInfoCallback;Offset         : Longint;beginPointer(FileNotifyInfo) := @FWatchBuf[0];repeat   Offset:=FileNotifyInfo^.NextEntryOffset;   InfoCallback.FAction:=FileNotifyInfo^.Action;   InfoCallback.FDrive:=FName;   SetString(InfoCallback.FNewFileName,FileNotifyInfo^.FileName,FileNotifyInfo^.FileNameLength);   InfoCallback.FNewFileName:=Trim(InfoCallback.FNewFileName);   case FileNotifyInfo^.Action of     FILE_ACTION_RENAMED_OLD_NAME:
FOldFileName:=Trim(WideCharToString(@(FileNotifyInfo^.FileName[0])));     FILE_ACTION_RENAMED_NEW_NAME: InfoCallback.FOldFileName:=FOldFileName;   end;   FInfoCallback(InfoCallback);   PChar(FileNotifyInfo):=PChar(FileNotifyInfo)+Offset;until (Offset=0) or Terminated;end; procedure TWFS.WatchEvent;varCompletionKey: Cardinal;beginFCompletionPort:=CreateIoCompletionPort(FWatchHandle, 0, Longint(pointer(self)), 0);ZeroMemory(@FWatchBuf, SizeOf(FWatchBuf));if not ReadDirectoryChanges(FWatchHandle, @FWatchBuf, SizeOf(FWatchBuf), FSubTree,   FFilter, @FBytesWritte,  @FOverLapp, nil) thenbegin   raise WFSError.Create(SysErrorMessage(GetLastError));   Terminate;end elsebegin   while not Terminated do   begin     GetQueuedCompletionStatus(FCompletionPort, FNumBytes, CompletionKey, FPOverLapp, INFINITE);     if CompletionKey<>0 then     begin       Synchronize(HandleEvent);       ZeroMemory(@FWatchBuf, SizeOf(FWatchBuf));       FBytesWritte:=0;       ReadDirectoryChanges(FWatchHandle, @FWatchBuf, SizeOf(FWatchBuf), FSubTree, FFilter,                            @FBytesWritte, @FOverLapp, nil);     end else Terminate;   endendend; end.    unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm)   Memo1: TMemo;   procedure FormCreate(Sender: TObject);   procedure FormDestroy(Sender: TObject);private   { Private declarations }public   { Public declarations }end; var Form1: TForm1; implementation {$R *.dfm} uses wfsU; procedure MyInfoCallback(pInfo: TInfoCallback);const begin   case pInfo.FAction of          [pInfo.FDrive+pInfo.FOldFileName,pInfo.FDrive+pInfo.FNewFileName]));   else     if pInfo.FAction<FILE_ACTION_RENAMED_OLD_NAME then       Form1.Memo1.Lines.Add(Format(Action[pInfo.Faction], [pInfo.FDrive+pInfo.FNewFileName]));   end;end; procedure TForm1.FormCreate(Sender: TObject);begin StartWatch('C:', FILE_NOTIFY_CHANGE_DIR_NAME, True, @MyInfoCallback);end; procedure TForm1.FormDestroy(Sender: TObject);beginStopWatchend; end.
|  | Ответ отправил: Feniks (статус: Бакалавр)Время отправки: 1 октября 2007, 15:50
 
 |  
 Мини-форум вопросаВсего сообщений: 1; последнее сообщение — 29 сентября 2007, 00:49; участников в обсуждении: 1. 
|   | Грег Леонов (статус: 1-ый класс), 29 сентября 2007, 00:49 [#1]:Код скопировался неудачно, выдели его и вставь в блокнот, легче прочесть будет. юзай ctrl + a, ctrl + c, ctrl + v |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |