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