ReactOS 0.4.16-dev-833-g4bc97ad
CDirectoryWatcher Class Reference

#include <CDirectoryWatcher.h>

Collaboration diagram for CDirectoryWatcher:

Public Member Functions

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

Static Public Member Functions

static CDirectoryWatcherCreate (HWND hNotifyWnd, 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 (HWND hNotifyWnd, LPCWSTR pszDirectoryPath, BOOL fSubTree)
 

Protected Attributes

HWND m_hNotifyWnd
 
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 103 of file CDirectoryWatcher.cpp.

104{
105 TRACE("%p, '%S'\n", this, m_szDirectoryPath);
106
109}
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 ( HWND  hNotifyWnd,
LPCWSTR  pszDirectoryPath,
BOOL  fSubTree 
)
protected

Definition at line 71 of file CDirectoryWatcher.cpp.

72 : m_hNotifyWnd(hNotifyWnd)
73 , m_fDead(FALSE)
74 , m_fRecursive(fSubTree)
75 , m_dir_list(pszDirectoryPath, fSubTree)
76{
77 TRACE("%p, '%S'\n", this, pszDirectoryPath);
78
80
81 // open the directory to watch changes (for ReadDirectoryChangesW)
86 NULL);
87}
CDirectoryList m_dir_list
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define OPEN_EXISTING
Definition: compat.h:775
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
#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
#define _countof(array)
Definition: sndvol32.h:70

Member Function Documentation

◆ Create()

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

Definition at line 90 of file CDirectoryWatcher.cpp.

91{
92 CDirectoryWatcher *pDirectoryWatcher =
93 new CDirectoryWatcher(hNotifyWnd, pszDirectoryPath, fSubTree);
94 if (pDirectoryWatcher->m_hDirectory == INVALID_HANDLE_VALUE)
95 {
96 ERR("CreateFileW failed\n");
97 delete pDirectoryWatcher;
98 pDirectoryWatcher = NULL;
99 }
100 return pDirectoryWatcher;
101}
#define ERR(fmt,...)
Definition: precomp.h:57

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 ( )

Definition at line 392 of file CDirectoryWatcher.cpp.

393{
395 {
397 m_fDead = TRUE;
399 }
400 return m_fDead;
401}
BOOL WINAPI CancelIo(IN HANDLE hFile)
Definition: deviceio.c:290
BOOL WINAPI IsWindow(_In_opt_ HWND)

Referenced by ReadCompletion(), and RestartWatching().

◆ ProcessNotification()

void CDirectoryWatcher::ProcessNotification ( )
protected

Definition at line 134 of file CDirectoryWatcher.cpp.

135{
138 DWORD dwEvent, cbName;
139 BOOL fDir;
140 TRACE("CDirectoryWatcher::ProcessNotification: enter\n");
141
142 // for each entry in s_buffer
143 szPath[0] = szTempPath[0] = 0;
144 for (;;)
145 {
146 // get name (relative from m_szDirectoryPath)
147 cbName = pInfo->FileNameLength;
148 if (sizeof(szName) - sizeof(UNICODE_NULL) < cbName)
149 {
150 ERR("pInfo->FileName is longer than szName\n");
151 break;
152 }
153 // NOTE: FILE_NOTIFY_INFORMATION.FileName is not null-terminated.
154 ZeroMemory(szName, sizeof(szName));
155 CopyMemory(szName, pInfo->FileName, cbName);
156
157 // get full path
160
161 // convert to long pathname if it contains '~'
162 if (StrChrW(szPath, L'~') != NULL)
163 {
166 {
168 }
169 }
170
171 // convert action to event
172 fDir = PathIsDirectoryW(szPath);
173 dwEvent = ConvertActionToEvent(pInfo->Action, fDir);
174
175 // convert SHCNE_DELETE to SHCNE_RMDIR if the path is a directory
176 if (!fDir && (dwEvent == SHCNE_DELETE) && m_dir_list.ContainsPath(szPath))
177 {
178 fDir = TRUE;
179 dwEvent = SHCNE_RMDIR;
180 }
181
182 // update m_dir_list
183 switch (dwEvent)
184 {
185 case SHCNE_MKDIR:
187 dwEvent = 0;
188 break;
189 case SHCNE_CREATE:
191 dwEvent = 0;
192 break;
195 dwEvent = 0;
196 break;
197 case SHCNE_RENAMEITEM:
199 dwEvent = 0;
200 break;
201 case SHCNE_RMDIR:
203 dwEvent = 0;
204 break;
205 case SHCNE_DELETE:
207 dwEvent = 0;
208 break;
209 }
210
211 if (dwEvent != 0)
212 {
213 // notify
216 else
218 }
219 else if (pInfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
220 {
221 // save path for next FILE_ACTION_RENAMED_NEW_NAME
223 }
224
225 if (pInfo->NextEntryOffset == 0)
226 break; // there is no next entry
227
228 // go next entry
229 pInfo = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pInfo + pInfo->NextEntryOffset);
230 }
231
232 TRACE("CDirectoryWatcher::ProcessNotification: leave\n");
233}
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:464
#define MAX_PATH
Definition: compat.h:34
#define lstrcpynW
Definition: compat.h:738
DWORD WINAPI GetLongPathNameW(IN LPCWSTR lpszShortPath, OUT LPWSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1456
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1783
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1729
BOOL WINAPI PathIsRelativeW(LPCWSTR lpszPath)
Definition: path.c:1585
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:1894
#define SHCNE_DELETE
Definition: shlobj.h:1892
#define SHCNE_MKDIR
Definition: shlobj.h:1893
#define SHCNE_RENAMEITEM
Definition: shlobj.h:1890
#define SHCNE_CREATE
Definition: shlobj.h:1891
#define SHCNE_RENAMEFOLDER
Definition: shlobj.h:1907
unsigned char * LPBYTE
Definition: typedefs.h:53
#define ZeroMemory
Definition: winbase.h:1737
#define CopyMemory
Definition: winbase.h:1735
struct _FILE_NOTIFY_INFORMATION * PFILE_NOTIFY_INFORMATION
#define FILE_ACTION_RENAMED_OLD_NAME
#define FILE_ACTION_RENAMED_NEW_NAME
__wchar_t WCHAR
Definition: xmlstorage.h:180

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;
390}
#define assert(x)
Definition: debug.h:53

Referenced by _RequestTerminationAPC().

◆ ReadCompletion()

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

Definition at line 235 of file CDirectoryWatcher.cpp.

236{
237 // If the FSD doesn't support directory change notifications, there's no
238 // no need to retry and requeue notification
239 if (dwErrorCode == ERROR_INVALID_FUNCTION)
240 {
241 ERR("ERROR_INVALID_FUNCTION\n");
242 return;
243 }
244
245 // Also, if the notify operation was canceled (like, user moved to another
246 // directory), then, don't requeue notification.
247 if (dwErrorCode == ERROR_OPERATION_ABORTED)
248 {
249 TRACE("ERROR_OPERATION_ABORTED\n");
250 if (IsDead())
251 delete this;
252 return;
253 }
254
255 // is this watch dead?
256 if (IsDead())
257 {
258 TRACE("IsDead()\n");
259 delete this;
260 return;
261 }
262
263 // This likely means overflow, so force whole directory refresh.
264 if (dwNumberOfBytesTransfered == 0)
265 {
266 // do notify a SHCNE_UPDATEDIR
268 }
269 else
270 {
271 // do notify
273 }
274
275 // restart a watch
277}
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
#define SHCNE_UPDATEDIR
Definition: shlobj.h:1902
#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:1914
HANDLE hEvent
Definition: winbase.h:845
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 35 of file CDirectoryWatcher.h.

Referenced by ProcessNotification().

◆ m_fDead

BOOL CDirectoryWatcher::m_fDead
protected

Definition at line 33 of file CDirectoryWatcher.h.

Referenced by IsDead(), and QuitWatching().

◆ m_fRecursive

BOOL CDirectoryWatcher::m_fRecursive
protected

Definition at line 34 of file CDirectoryWatcher.h.

Referenced by RestartWatching().

◆ m_hDirectory

HANDLE CDirectoryWatcher::m_hDirectory

◆ m_hNotifyWnd

HWND CDirectoryWatcher::m_hNotifyWnd
protected

Definition at line 32 of file CDirectoryWatcher.h.

Referenced by IsDead(), and QuitWatching().

◆ m_overlapped

OVERLAPPED CDirectoryWatcher::m_overlapped
protected

Definition at line 36 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: