procedure CtrlThread.Execute;
var
pBuffer : Pointer; // Buffer for return values of ReadDirectoryChangesW
dwBufLen : DWORD;
dwRead : DWORD;
PInfo : PFILE_NOTIFY_INFORMATION;
dwNextOfs : DWORD;
dwFnLen : DWORD;
Overlap : TOverlapped;
WaitResult: DWORD;
EventArray: Array[0..2] of THandle; // Array der Handles für WaitForMultipleObjects
pFileNameForMessage: PWideChar;
lasterrcode:Cardinal; ErrorMessage: string;
begin
try // try .. except
Cancel_IO;
if not DirectoryExists(FsDirPath) then begin
Terminate;
exit;
end;
FhFile:= CreateFileW(PWideChar(UTF8Decode(FsDirPath)),
FILE_LIST_DIRECTORY or GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,
0);
if (FhFile = INVALID_HANDLE_VALUE) or (FhFile = 0) then begin
Terminate;
exit;
end;
FileEvent:=CreateEvent(nil,FALSE,FALSE,nil);
Overlap.hEvent:=FileEvent;
TermEvent:=TEvent.Create(nil,FALSE,FALSE,TermEvName);
SuspEvent:=TEvent.Create(nil,FALSE,FALSE,SuspEvName);
EventArray[0]:=FileEvent;
EventArray[1]:=TermEvent.Handle;
EventArray[2]:=SuspEvent.Handle;
}
EventArray[0] := FileEvent;
EventArray[1] := plocaleventrec(TermEvent.Handle)^.Fhandle;
EventArray[2] := plocaleventrec(SuspEvent.Handle)^.Fhandle;
dwBufLen := 65535; // Dirwatch: BufferSize (=32) * SizeOf(TFILE_NOTIFY_INFORMATION);
pBuffer := AllocMem(dwBufLen);
try
while not terminated do begin
dwRead := 0;
if ReadDirectoryChangesW(FhFile, pBuffer, dwBufLen,
prWatchSubTree, // true or false didn't make a difference here
FFilter, //FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME,
@dwRead, @Overlap, NIL) then
begin
WaitResult := WaitForMultipleObjects(3, @EventArray, FALSE, infinite);
case WaitResult of
WaitDir:
begin // WAIT_OBJECT_0
if GetOverlappedResult(FhFile, Overlap, dwRead, False) then begin
PInfo:= pBuffer;
if dwRead = 0 then begin // check overflow
ErrorMessage := SysErrorMessage(ERROR_NOTIFY_ENUM_DIR);
SignalError(ErrorMessage, ERROR_NOTIFY_ENUM_DIR);
end;
repeat
dwNextOfs := PInfo.dwNextEntryOffset;
FAction := PInfo.dwAction;
dwFnLen := PInfo.dwFileNameLength;
FsFileName := WideCharLenToString(@PInfo.dwFileName,dwFnLen div 2);
GetMem(pFileNameForMessage, dwFnLen + SizeOf(WideChar));
Move(PInfo.dwFileName, Pointer(pFileNameForMessage)^, dwFnLen);
PWord(Cardinal(pFileNameForMessage) + dwFnLen)^ := 0;
PostMessage(FWndHandle, WM_DIRWATCH_NOTIFY, FAction, LParam(pFileNameForMessage));
pChar(PInfo) := pChar(PInfo)+dwNextOfs;
until dwNextOfs=0;
end else begin
lasterrcode := GetLastError;
ErrorMessage := SysErrorMessage(lasterrcode);
SignalError(ErrorMessage, lasterrcode);
break;
end; // GetOverlappedResult
end;
WaitTerm: // WAIT_OBJECT_0+1
// dont call Terminate again here
;
WaitSusp: Suspend; // WAIT_OBJECT_0+2
else
break;
end; // case WaitResult ReadDirectoryChangesW
end else begin
ErrorMessage := SysErrorMessage(GetLastError);
SignalError(ErrorMessage);
end;
end;
finally
FreeMem(pBuffer,dwBufLen);
if FhFile <> 0 then
if FhFile <> INVALID_HANDLE_VALUE then begin
CancelIOEx(FhFile, 0); // or nil, no change
CloseHandle(FhFile);
FhFile := 0;
end;
SendMessage(FWndHandle, WM_DIRWATCH_THREADTERMINATED, 0, 0);
with TFldrControl(Owner) do
ThrdTerminated := True;
end; // try
except
on E :Exception do begin
ErrorMessage := E.Message;
SignalError(ErrorMessage);
end;
end;
end;