1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include <efsw/String.hpp>
#include <efsw/WatcherWin32.hpp>
#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
namespace efsw {
/// Unpacks events and passes them to a user defined callback.
void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) {
if ( dwNumberOfBytesTransfered == 0 || NULL == lpOverlapped ) {
return;
}
char szFile[MAX_PATH];
PFILE_NOTIFY_INFORMATION pNotify;
WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped;
WatcherWin32* pWatch = tWatch->Watch;
size_t offset = 0;
do {
bool skip = false;
pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset];
offset += pNotify->NextEntryOffset;
int count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName,
pNotify->FileNameLength / sizeof( WCHAR ), szFile,
MAX_PATH - 1, NULL, NULL );
szFile[count] = TEXT( '\0' );
std::string nfile( szFile );
if ( FILE_ACTION_MODIFIED == pNotify->Action ) {
FileInfo fifile( std::string( pWatch->DirName ) + nfile );
if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime &&
pWatch->LastModifiedEvent.file.Size == fifile.Size &&
pWatch->LastModifiedEvent.fileName == nfile ) {
skip = true;
}
pWatch->LastModifiedEvent.fileName = nfile;
pWatch->LastModifiedEvent.file = fifile;
}
if ( !skip ) {
pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action );
}
} while ( pNotify->NextEntryOffset != 0 );
if ( !pWatch->StopNow ) {
RefreshWatch( tWatch );
}
}
/// Refreshes the directory monitoring.
bool RefreshWatch( WatcherStructWin32* pWatch ) {
return ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer,
sizeof( pWatch->Watch->Buffer ), pWatch->Watch->Recursive,
pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped,
NULL ) != 0;
}
/// Stops monitoring a directory.
void DestroyWatch( WatcherStructWin32* pWatch ) {
if ( pWatch ) {
WatcherWin32* tWatch = pWatch->Watch;
tWatch->StopNow = true;
CancelIoEx( pWatch->Watch->DirHandle, &pWatch->Overlapped );
CloseHandle( pWatch->Watch->DirHandle );
efSAFE_DELETE_ARRAY( pWatch->Watch->DirName );
efSAFE_DELETE( pWatch->Watch );
}
}
/// Starts monitoring a directory.
WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter,
HANDLE iocp ) {
WatcherStructWin32* tWatch;
size_t ptrsize = sizeof( *tWatch );
tWatch = static_cast<WatcherStructWin32*>(
HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize ) );
WatcherWin32* pWatch = new WatcherWin32();
tWatch->Watch = pWatch;
pWatch->DirHandle = CreateFileW(
szDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL );
if ( pWatch->DirHandle != INVALID_HANDLE_VALUE &&
CreateIoCompletionPort( pWatch->DirHandle, iocp, 0, 1 ) ) {
pWatch->NotifyFilter = NotifyFilter;
pWatch->Recursive = recursive;
if ( RefreshWatch( tWatch ) ) {
return tWatch;
}
}
CloseHandle( pWatch->DirHandle );
efSAFE_DELETE( pWatch->Watch );
HeapFree( GetProcessHeap(), 0, tWatch );
return NULL;
}
} // namespace efsw
#endif
|