Function DCSourceChangesThread(
DC: TDirectoryCompare): LongWord;
StdCall;
Const BufferSize = 4096
{65536};
Var DH, NH: THandle;
Buffer, P: PWideChar;
Name: Widestring;
Status: TDCObjStatus;
i: Integer;
W: LongWord;
Label LExit;
Begin
Result := 0;
DH := CreateFileW(PWideChar(Copy(
DC._SourceRoot, 1, Length(
DC._SourceRoot) - 1)), GENERIC_READ
or FILE_LIST_DIRECTORY,
FILE_SHARE_READ
or FILE_SHARE_WRITE
or FILE_SHARE_DELETE,
nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
NH := FindFirstChangeNotificationW(PWideChar(Copy(
DC._SourceRoot, 1, Length(
DC._SourceRoot) - 1)),
True, 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_CREATION);
Buffer := GetMemory(BufferSize);
If (DH <> INVALID_HANDLE_VALUE)
and (NH <> INVALID_HANDLE_VALUE)
and (Buffer <>
nil)
Then
Repeat
If (
DC._DestChangesThread = INVALID_HANDLE_VALUE)
or (
DC._Pause = 2)
Then GoTo LExit;
Case WaitForSingleObject(NH, 1000)
of
WAIT_FAILED: Break;
WAIT_OBJECT_0:
If ReadDirectoryChangesW(DH, Buffer, BufferSize, True, 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_CREATION, @W,
nil,
nil)
Then Begin
P := Buffer;
Repeat
SetLength(
Name, PFileNotifiInformation(P)^.FileNameLength
div 2);
Move(PFileNotifiInformation(P)^.FileName,
Name[1], PFileNotifiInformation(P)^.FileNameLength + 1);
Case PFileNotifiInformation(P)^.Action
of
FILE_ACTION_ADDED: Status := [dcsDeleted];
FILE_ACTION_REMOVED: Status := [dcsCreated];
FILE_ACTION_MODIFIED: Status := [dcsSize..dcsLastWriteTime, dcsContent..dcsAttrEncrypted];
FILE_ACTION_RENAMED_OLD_NAME: Status := [dcsName];
FILE_ACTION_RENAMED_NEW_NAME: Status := [dcsName];
Else Status := [dcsSize..dcsAttrEncrypted];
End;
Lock(
DC._Lock);
i := High(
DC._SourceChangesList);
While i >= 0
do
If WideSameText(
DC._SourceChangesList[i].
Name,
Name)
Then Break
Else Dec(i);
If i < 0
Then Begin
i := Length(
DC._SourceChangesList);
SetLength(
DC._SourceChangesList, i + 1);
DC._SourceChangesList[i].
Name :=
Name;
//UniqueString(DC._SourceChangesList[i].Name); // WideString/OLE-String is always an UniqueString.
DC._SourceChangesList[i].Changes := [];
End;
DC._SourceChangesList[i].Changes :=
DC._SourceChangesList[i].Changes + Status;
DC._SourceChangesList[i].Time := GetTickCount;
Unlock(
DC._Lock);
P := Buffer + PFileNotifiInformation(P)^.NextEntryOffset;
Until PFileNotifiInformation(P)^.NextEntryOffset = 0;
End Else Break;
End;
Until not FindNextChangeNotification(NH);
DC._CallStatusProc(dcsErrorSourceDirChangesThread, '
', Integer(
DC));
LExit:
FreeMemory(Buffer);
FindCloseChangeNotification(NH);
CloseHandle(DH);
LockedSet(
DC._SourceChangesThread, INVALID_HANDLE_VALUE);
End;