ReactOS 0.4.15-dev-7842-g558ab78
CDirectoryWatcher Class Reference

#include <CDirectoryWatcher.h>

Collaboration diagram for CDirectoryWatcher:

Public Member Functions

 ~CDirectoryWatcher ()
 
BOOL IsDead () const
 
BOOL RestartWatching ()
 
void QuitWatching ()
 
BOOL RequestAddWatcher ()
 
BOOL RequestTermination ()
 
void ReadCompletion (DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered)
 

Static Public Member Functions

static CDirectoryWatcherCreate (LPCWSTR pszDirectoryPath, BOOL fSubTree)
 
static void RequestAllWatchersTermination ()
 

Public Attributes

HANDLE m_hDirectory
 
WCHAR m_szDirectoryPath [MAX_PATH]
 

Protected Member Functions

BOOL CreateAPCThread ()
 
void ProcessNotification ()
 
 CDirectoryWatcher (LPCWSTR pszDirectoryPath, BOOL fSubTree)
 

Protected Attributes

BOOL m_fDead
 
BOOL m_fRecursive
 
CDirectoryList m_dir_list
 
OVERLAPPED m_overlapped
 

Detailed Description

Definition at line 14 of file CDirectoryWatcher.h.

Constructor & Destructor Documentation

◆ ~CDirectoryWatcher()

CDirectoryWatcher::~CDirectoryWatcher ( )

Definition at line 104 of file CDirectoryWatcher.cpp.

105{
106 TRACE("CDirectoryWatcher::~CDirectoryWatcher: %p, '%S'\n", this, m_szDirectoryPath);
107
110}
WCHAR m_szDirectoryPath[MAX_PATH]
#define CloseHandle
Definition: compat.h:739
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define TRACE(s)
Definition: solgame.cpp:4

◆ CDirectoryWatcher()

CDirectoryWatcher::CDirectoryWatcher ( LPCWSTR  pszDirectoryPath,
BOOL  fSubTree 
)
protected

Definition at line 71 of file CDirectoryWatcher.cpp.

72 : m_fDead(FALSE)
73 , m_fRecursive(fSubTree)
74 , m_dir_list(pszDirectoryPath, fSubTree)
75{
76 TRACE("CDirectoryWatcher::CDirectoryWatcher: %p, '%S'\n", this, pszDirectoryPath);
77
78 lstrcpynW(m_szDirectoryPath, pszDirectoryPath, MAX_PATH);
79
80 // open the directory to watch changes (for ReadDirectoryChangesW)
85 NULL);
86}
CDirectoryList m_dir_list
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define OPEN_EXISTING
Definition: compat.h:775
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrcpynW
Definition: compat.h:738
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
#define FILE_SHARE_DELETE
Definition: nt_native.h:682

Member Function Documentation

◆ Create()

CDirectoryWatcher * CDirectoryWatcher::Create ( LPCWSTR  pszDirectoryPath,
BOOL  fSubTree 
)
static

Definition at line 89 of file CDirectoryWatcher.cpp.

90{
91 WCHAR szFullPath[MAX_PATH];
92 GetFullPathNameW(pszDirectoryPath, _countof(szFullPath), szFullPath, NULL);
93
94 CDirectoryWatcher *pDirectoryWatcher = new CDirectoryWatcher(szFullPath, fSubTree);
95 if (pDirectoryWatcher->m_hDirectory == INVALID_HANDLE_VALUE)
96 {
97 ERR("CreateFileW failed\n");
98 delete pDirectoryWatcher;
99 pDirectoryWatcher = NULL;
100 }
101 return pDirectoryWatcher;
102}
#define ERR(fmt,...)
Definition: debug.h:110
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
#define _countof(array)
Definition: sndvol32.h:68
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CreateDirectoryWatcherFromRegEntry().

◆ CreateAPCThread()

BOOL CDirectoryWatcher::CreateAPCThread ( )
protected

Definition at line 336 of file CDirectoryWatcher.cpp.

337{
338 if (s_hThreadAPC != NULL)
339 return TRUE;
340
341 unsigned tid;
344 NULL, 0, &tid);
345 return s_hThreadAPC != NULL;
346}
static BOOL s_fTerminateAllWatchers
static HANDLE s_hThreadAPC
static unsigned __stdcall DirectoryWatcherThreadFuncAPC(void *)
#define TRUE
Definition: types.h:120
static TfClientId tid
_CRTIMP uintptr_t __cdecl _beginthreadex(_In_opt_ void *_Security, _In_ unsigned _StackSize, _In_ unsigned(__stdcall *_StartAddress)(void *), _In_opt_ void *_ArgList, _In_ unsigned _InitFlag, _Out_opt_ unsigned *_ThrdAddr)
PVOID HANDLE
Definition: typedefs.h:73

Referenced by RequestAddWatcher().

◆ IsDead()

BOOL CDirectoryWatcher::IsDead ( ) const

Definition at line 391 of file CDirectoryWatcher.cpp.

392{
393 return m_fDead;
394}

Referenced by ReadCompletion(), and RestartWatching().

◆ ProcessNotification()

void CDirectoryWatcher::ProcessNotification ( )
protected

Definition at line 135 of file CDirectoryWatcher.cpp.

136{
139 DWORD dwEvent, cbName;
140 BOOL fDir;
141 TRACE("CDirectoryWatcher::ProcessNotification: enter\n");
142
143 // for each entry in s_buffer
144 szPath[0] = szTempPath[0] = 0;
145 for (;;)
146 {
147 // get name (relative from m_szDirectoryPath)
148 cbName = pInfo->FileNameLength;
149 if (sizeof(szName) - sizeof(UNICODE_NULL) < cbName)
150 {
151 ERR("pInfo->FileName is longer than szName\n");
152 break;
153 }
154 // NOTE: FILE_NOTIFY_INFORMATION.FileName is not null-terminated.
155 ZeroMemory(szName, sizeof(szName));
156 CopyMemory(szName, pInfo->FileName, cbName);
157
158 // get full path
161
162 // convert to long pathname if it contains '~'
163 if (StrChrW(szPath, L'~') != NULL)
164 {
167 {
169 }
170 }
171
172 // convert action to event
173 fDir = PathIsDirectoryW(szPath);
174 dwEvent = ConvertActionToEvent(pInfo->Action, fDir);
175
176 // convert SHCNE_DELETE to SHCNE_RMDIR if the path is a directory
177 if (!fDir && (dwEvent == SHCNE_DELETE) && m_dir_list.ContainsPath(szPath))
178 {
179 fDir = TRUE;
180 dwEvent = SHCNE_RMDIR;
181 }
182
183 // update m_dir_list
184 switch (dwEvent)
185 {
186 case SHCNE_MKDIR:
188 dwEvent = 0;
189 break;
190 case SHCNE_CREATE:
192 dwEvent = 0;
193 break;
196 dwEvent = 0;
197 break;
198 case SHCNE_RENAMEITEM:
200 dwEvent = 0;
201 break;
202 case SHCNE_RMDIR:
204 dwEvent = 0;
205 break;
206 case SHCNE_DELETE:
208 dwEvent = 0;
209 break;
210 }
211
212 if (dwEvent != 0)
213 {
214 // notify
217 else
219 }
220 else if (pInfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
221 {
222 // save path for next FILE_ACTION_RENAMED_NEW_NAME
224 }
225
226 if (pInfo->NextEntryOffset == 0)
227 break; // there is no next entry
228
229 // go next entry
230 pInfo = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pInfo + pInfo->NextEntryOffset);
231 }
232
233 TRACE("CDirectoryWatcher::ProcessNotification: leave\n");
234}
static void NotifyFileSystemChange(LONG wEventId, LPCWSTR path1, LPCWSTR path2)
static BYTE s_buffer[BUFFER_SIZE]
static DWORD ConvertActionToEvent(DWORD Action, BOOL fDir)
BOOL AddPath(LPCWSTR pszPath)
BOOL ContainsPath(LPCWSTR pszPath) const
BOOL DeletePath(LPCWSTR pszPath)
BOOL RenamePath(LPCWSTR pszPath1, LPCWSTR pszPath2)
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
DWORD WINAPI GetLongPathNameW(IN LPCWSTR lpszShortPath, OUT LPWSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1456
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1723
BOOL WINAPI PathIsRelativeW(LPCWSTR lpszPath)
Definition: path.c:1579
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
LPCWSTR szPath
Definition: env.c:37
static char szTempPath[MAX_PATH]
Definition: data.c:16
#define UNICODE_NULL
#define L(x)
Definition: ntvdm.h:50
#define PathAppendW
Definition: pathcch.h:309
static const WCHAR szName[]
Definition: powrprof.c:45
#define SHCNE_RMDIR
Definition: shlobj.h:1879
#define SHCNE_DELETE
Definition: shlobj.h:1877
#define SHCNE_MKDIR
Definition: shlobj.h:1878
#define SHCNE_RENAMEITEM
Definition: shlobj.h:1875
#define SHCNE_CREATE
Definition: shlobj.h:1876
#define SHCNE_RENAMEFOLDER
Definition: shlobj.h:1892
unsigned char * LPBYTE
Definition: typedefs.h:53
#define ZeroMemory
Definition: winbase.h:1712
#define CopyMemory
Definition: winbase.h:1710
struct _FILE_NOTIFY_INFORMATION * PFILE_NOTIFY_INFORMATION
#define FILE_ACTION_RENAMED_OLD_NAME
#define FILE_ACTION_RENAMED_NEW_NAME

Referenced by ReadCompletion().

◆ QuitWatching()

void CDirectoryWatcher::QuitWatching ( )

Definition at line 383 of file CDirectoryWatcher.cpp.

384{
385 assert(this != NULL);
386
387 m_fDead = TRUE;
389}
BOOL WINAPI CancelIo(IN HANDLE hFile)
Definition: deviceio.c:290
#define assert(x)
Definition: debug.h:53

Referenced by _RequestTerminationAPC().

◆ ReadCompletion()

void CDirectoryWatcher::ReadCompletion ( DWORD  dwErrorCode,
DWORD  dwNumberOfBytesTransfered 
)

Definition at line 236 of file CDirectoryWatcher.cpp.

237{
238 // If the FSD doesn't support directory change notifications, there's no
239 // no need to retry and requeue notification
240 if (dwErrorCode == ERROR_INVALID_FUNCTION)
241 {
242 ERR("ERROR_INVALID_FUNCTION\n");
243 return;
244 }
245
246 // Also, if the notify operation was canceled (like, user moved to another
247 // directory), then, don't requeue notification.
248 if (dwErrorCode == ERROR_OPERATION_ABORTED)
249 {
250 TRACE("ERROR_OPERATION_ABORTED\n");
251 if (IsDead())
252 delete this;
253 return;
254 }
255
256 // is this watch dead?
257 if (IsDead())
258 {
259 TRACE("IsDead()\n");
260 delete this;
261 return;
262 }
263
264 // This likely means overflow, so force whole directory refresh.
265 if (dwNumberOfBytesTransfered == 0)
266 {
267 // do notify a SHCNE_UPDATEDIR
269 }
270 else
271 {
272 // do notify
274 }
275
276 // restart a watch
278}
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
#define SHCNE_UPDATEDIR
Definition: shlobj.h:1887
#define ERROR_OPERATION_ABORTED
Definition: winerror.h:575

Referenced by _NotificationCompletion().

◆ RequestAddWatcher()

BOOL CDirectoryWatcher::RequestAddWatcher ( )

Definition at line 348 of file CDirectoryWatcher.cpp.

349{
350 assert(this != NULL);
351
352 // create an APC thread for directory watching
353 if (!CreateAPCThread())
354 return FALSE;
355
356 // request adding the watch
358 return TRUE;
359}
static void NTAPI _AddDirectoryProcAPC(ULONG_PTR Parameter)
DWORD WINAPI QueueUserAPC(IN PAPCFUNC pfnAPC, IN HANDLE hThread, IN ULONG_PTR dwData)
Definition: thread.c:959
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by CChangeNotifyServer::OnRegister().

◆ RequestAllWatchersTermination()

void CDirectoryWatcher::RequestAllWatchersTermination ( )
static

Definition at line 374 of file CDirectoryWatcher.cpp.

375{
376 if (!s_hThreadAPC)
377 return;
378
379 // request termination of all directory watches
381}
static void NTAPI _RequestAllTerminationAPC(ULONG_PTR Parameter)

Referenced by CChangeNotifyServer::OnDestroy().

◆ RequestTermination()

BOOL CDirectoryWatcher::RequestTermination ( )

Definition at line 361 of file CDirectoryWatcher.cpp.

362{
363 assert(this != NULL);
364
365 if (s_hThreadAPC)
366 {
368 return TRUE;
369 }
370
371 return FALSE;
372}
static void NTAPI _RequestTerminationAPC(ULONG_PTR Parameter)

Referenced by CChangeNotifyServer::DestroyItem().

◆ RestartWatching()

BOOL CDirectoryWatcher::RestartWatching ( )

Definition at line 307 of file CDirectoryWatcher.cpp.

308{
309 assert(this != NULL);
310
311 if (IsDead())
312 {
313 delete this;
314 return FALSE; // the watch is dead
315 }
316
317 // initialize the buffer and the overlapped
318 ZeroMemory(s_buffer, sizeof(s_buffer));
320 m_overlapped.hEvent = (HANDLE)this;
321
322 // start the directory watch
325 m_fRecursive, dwFilter, NULL,
327 {
328 ERR("ReadDirectoryChangesW for '%S' failed (error: %ld)\n",
330 return FALSE; // failure
331 }
332
333 return TRUE; // success
334}
static DWORD GetFilterFromEvents(DWORD fEvents)
static void CALLBACK _NotificationCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
BOOL WINAPI ReadDirectoryChangesW(IN HANDLE hDirectory, IN LPVOID lpBuffer OPTIONAL, IN DWORD nBufferLength, IN BOOL bWatchSubtree, IN DWORD dwNotifyFilter, OUT LPDWORD lpBytesReturned, IN LPOVERLAPPED lpOverlapped OPTIONAL, IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: cnotify.c:253
#define SHCNE_ALLEVENTS
Definition: shlobj.h:1899
HANDLE hEvent
Definition: winbase.h:820
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

Referenced by _AddDirectoryProcAPC(), and ReadCompletion().

Member Data Documentation

◆ m_dir_list

CDirectoryList CDirectoryWatcher::m_dir_list
protected

Definition at line 34 of file CDirectoryWatcher.h.

Referenced by ProcessNotification().

◆ m_fDead

BOOL CDirectoryWatcher::m_fDead
protected

Definition at line 32 of file CDirectoryWatcher.h.

Referenced by IsDead(), and QuitWatching().

◆ m_fRecursive

BOOL CDirectoryWatcher::m_fRecursive
protected

Definition at line 33 of file CDirectoryWatcher.h.

Referenced by RestartWatching().

◆ m_hDirectory

HANDLE CDirectoryWatcher::m_hDirectory

◆ m_overlapped

OVERLAPPED CDirectoryWatcher::m_overlapped
protected

Definition at line 35 of file CDirectoryWatcher.h.

Referenced by RestartWatching().

◆ m_szDirectoryPath

WCHAR CDirectoryWatcher::m_szDirectoryPath[MAX_PATH]

The documentation for this class was generated from the following files: