ReactOS 0.4.15-dev-8227-g32d615f
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: debug.h:113

Referenced by CreateDirectoryWatcherFromRegEntry().

◆ CreateAPCThread()

BOOL CDirectoryWatcher::CreateAPCThread ( )
protected

Definition at line 335 of file CDirectoryWatcher.cpp.

336{
337 if (s_hThreadAPC != NULL)
338 return TRUE;
339
340 unsigned tid;
343 NULL, 0, &tid);
344 return s_hThreadAPC != NULL;
345}
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 391 of file CDirectoryWatcher.cpp.

392{
394 {
396 m_fDead = TRUE;
398 }
399 return m_fDead;
400}
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:468
#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: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:1887
#define SHCNE_DELETE
Definition: shlobj.h:1885
#define SHCNE_MKDIR
Definition: shlobj.h:1886
#define SHCNE_RENAMEITEM
Definition: shlobj.h:1883
#define SHCNE_CREATE
Definition: shlobj.h:1884
#define SHCNE_RENAMEFOLDER
Definition: shlobj.h:1900
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
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by ReadCompletion().

◆ QuitWatching()

void CDirectoryWatcher::QuitWatching ( )

Definition at line 382 of file CDirectoryWatcher.cpp.

383{
384 assert(this != NULL);
385
386 m_fDead = TRUE;
389}
#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:1895
#define ERROR_OPERATION_ABORTED
Definition: winerror.h:575

Referenced by _NotificationCompletion().

◆ RequestAddWatcher()

BOOL CDirectoryWatcher::RequestAddWatcher ( )

Definition at line 347 of file CDirectoryWatcher.cpp.

348{
349 assert(this != NULL);
350
351 // create an APC thread for directory watching
352 if (!CreateAPCThread())
353 return FALSE;
354
355 // request adding the watch
357 return TRUE;
358}
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 373 of file CDirectoryWatcher.cpp.

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

Referenced by CChangeNotifyServer::OnDestroy().

◆ RequestTermination()

BOOL CDirectoryWatcher::RequestTermination ( )

Definition at line 360 of file CDirectoryWatcher.cpp.

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

Referenced by CChangeNotifyServer::DestroyItem().

◆ RestartWatching()

BOOL CDirectoryWatcher::RestartWatching ( )

Definition at line 306 of file CDirectoryWatcher.cpp.

307{
308 assert(this != NULL);
309
310 if (IsDead())
311 {
312 delete this;
313 return FALSE; // the watch is dead
314 }
315
316 // initialize the buffer and the overlapped
317 ZeroMemory(s_buffer, sizeof(s_buffer));
319 m_overlapped.hEvent = (HANDLE)this;
320
321 // start the directory watch
324 m_fRecursive, dwFilter, NULL,
326 {
327 ERR("ReadDirectoryChangesW for '%S' failed (error: %ld)\n",
329 return FALSE; // failure
330 }
331
332 return TRUE; // success
333}
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:1907
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 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: