1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * FILE: notificationtest.c
3*c2c66affSColin Finck * PURPOSE: Files notifications testing
4*c2c66affSColin Finck * NOTES: MSDN code from: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365261%28v=vs.85%29.aspx
5*c2c66affSColin Finck */
6*c2c66affSColin Finck
7*c2c66affSColin Finck #include <windows.h>
8*c2c66affSColin Finck #include <stdlib.h>
9*c2c66affSColin Finck #include <stdio.h>
10*c2c66affSColin Finck #include <tchar.h>
11*c2c66affSColin Finck
12*c2c66affSColin Finck #if defined(_tsplitpath) && !defined(_tsplitpath_s)
13*c2c66affSColin Finck #define _tsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _tsplitpath(f, d, p, n, e)
14*c2c66affSColin Finck #else
15*c2c66affSColin Finck #define _wsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _wsplitpath(f, d, p, n, e)
16*c2c66affSColin Finck #define _splitpath_s(f, d,dl, p,pl, n,nl, e,el) _splitpath(f, d, p, n, e)
17*c2c66affSColin Finck #endif
18*c2c66affSColin Finck
19*c2c66affSColin Finck void RefreshDirectory(LPTSTR);
20*c2c66affSColin Finck void RefreshTree(LPTSTR);
21*c2c66affSColin Finck void WatchDirectory(LPTSTR);
22*c2c66affSColin Finck
_tmain(int argc,TCHAR * argv[])23*c2c66affSColin Finck int _tmain(int argc, TCHAR *argv[])
24*c2c66affSColin Finck {
25*c2c66affSColin Finck if(argc != 2)
26*c2c66affSColin Finck {
27*c2c66affSColin Finck _tprintf(TEXT("Usage: %s <dir>\n"), argv[0]);
28*c2c66affSColin Finck return -1;
29*c2c66affSColin Finck }
30*c2c66affSColin Finck
31*c2c66affSColin Finck WatchDirectory(argv[1]);
32*c2c66affSColin Finck
33*c2c66affSColin Finck return 0;
34*c2c66affSColin Finck }
35*c2c66affSColin Finck
WatchDirectory(LPTSTR lpDir)36*c2c66affSColin Finck void WatchDirectory(LPTSTR lpDir)
37*c2c66affSColin Finck {
38*c2c66affSColin Finck DWORD dwWaitStatus;
39*c2c66affSColin Finck HANDLE dwChangeHandles[2];
40*c2c66affSColin Finck TCHAR lpDrive[4];
41*c2c66affSColin Finck TCHAR lpFile[_MAX_FNAME];
42*c2c66affSColin Finck TCHAR lpExt[_MAX_EXT];
43*c2c66affSColin Finck
44*c2c66affSColin Finck _tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);
45*c2c66affSColin Finck
46*c2c66affSColin Finck lpDrive[2] = (TCHAR)'\\';
47*c2c66affSColin Finck lpDrive[3] = (TCHAR)'\0';
48*c2c66affSColin Finck
49*c2c66affSColin Finck // Watch the directory for file creation and deletion.
50*c2c66affSColin Finck
51*c2c66affSColin Finck dwChangeHandles[0] = FindFirstChangeNotification(
52*c2c66affSColin Finck lpDir, // directory to watch
53*c2c66affSColin Finck FALSE, // do not watch subtree
54*c2c66affSColin Finck FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
55*c2c66affSColin Finck
56*c2c66affSColin Finck if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
57*c2c66affSColin Finck {
58*c2c66affSColin Finck printf("\n ERROR: FindFirstChangeNotification function failed.\n");
59*c2c66affSColin Finck ExitProcess(GetLastError());
60*c2c66affSColin Finck }
61*c2c66affSColin Finck
62*c2c66affSColin Finck // Watch the subtree for directory creation and deletion.
63*c2c66affSColin Finck
64*c2c66affSColin Finck dwChangeHandles[1] = FindFirstChangeNotification(
65*c2c66affSColin Finck lpDrive, // directory to watch
66*c2c66affSColin Finck TRUE, // watch the subtree
67*c2c66affSColin Finck FILE_NOTIFY_CHANGE_DIR_NAME); // watch dir name changes
68*c2c66affSColin Finck
69*c2c66affSColin Finck if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
70*c2c66affSColin Finck {
71*c2c66affSColin Finck printf("\n ERROR: FindFirstChangeNotification function failed.\n");
72*c2c66affSColin Finck ExitProcess(GetLastError());
73*c2c66affSColin Finck }
74*c2c66affSColin Finck
75*c2c66affSColin Finck
76*c2c66affSColin Finck // Make a final validation check on our handles.
77*c2c66affSColin Finck
78*c2c66affSColin Finck if ((dwChangeHandles[0] == NULL) || (dwChangeHandles[1] == NULL))
79*c2c66affSColin Finck {
80*c2c66affSColin Finck printf("\n ERROR: Unexpected NULL from FindFirstChangeNotification.\n");
81*c2c66affSColin Finck ExitProcess(GetLastError());
82*c2c66affSColin Finck }
83*c2c66affSColin Finck
84*c2c66affSColin Finck // Change notification is set. Now wait on both notification
85*c2c66affSColin Finck // handles and refresh accordingly.
86*c2c66affSColin Finck
87*c2c66affSColin Finck while (TRUE)
88*c2c66affSColin Finck {
89*c2c66affSColin Finck // Wait for notification.
90*c2c66affSColin Finck
91*c2c66affSColin Finck printf("\nWaiting for notification...\n");
92*c2c66affSColin Finck
93*c2c66affSColin Finck dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles,
94*c2c66affSColin Finck FALSE, INFINITE);
95*c2c66affSColin Finck
96*c2c66affSColin Finck switch (dwWaitStatus)
97*c2c66affSColin Finck {
98*c2c66affSColin Finck case WAIT_OBJECT_0:
99*c2c66affSColin Finck
100*c2c66affSColin Finck // A file was created, renamed, or deleted in the directory.
101*c2c66affSColin Finck // Refresh this directory and restart the notification.
102*c2c66affSColin Finck
103*c2c66affSColin Finck RefreshDirectory(lpDir);
104*c2c66affSColin Finck if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE )
105*c2c66affSColin Finck {
106*c2c66affSColin Finck printf("\n ERROR: FindNextChangeNotification function failed.\n");
107*c2c66affSColin Finck ExitProcess(GetLastError());
108*c2c66affSColin Finck }
109*c2c66affSColin Finck break;
110*c2c66affSColin Finck
111*c2c66affSColin Finck case WAIT_OBJECT_0 + 1:
112*c2c66affSColin Finck
113*c2c66affSColin Finck // A directory was created, renamed, or deleted.
114*c2c66affSColin Finck // Refresh the tree and restart the notification.
115*c2c66affSColin Finck
116*c2c66affSColin Finck RefreshTree(lpDrive);
117*c2c66affSColin Finck if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE )
118*c2c66affSColin Finck {
119*c2c66affSColin Finck printf("\n ERROR: FindNextChangeNotification function failed.\n");
120*c2c66affSColin Finck ExitProcess(GetLastError());
121*c2c66affSColin Finck }
122*c2c66affSColin Finck break;
123*c2c66affSColin Finck
124*c2c66affSColin Finck case WAIT_TIMEOUT:
125*c2c66affSColin Finck
126*c2c66affSColin Finck // A timeout occurred, this would happen if some value other
127*c2c66affSColin Finck // than INFINITE is used in the Wait call and no changes occur.
128*c2c66affSColin Finck // In a single-threaded environment you might not want an
129*c2c66affSColin Finck // INFINITE wait.
130*c2c66affSColin Finck
131*c2c66affSColin Finck printf("\nNo changes in the timeout period.\n");
132*c2c66affSColin Finck break;
133*c2c66affSColin Finck
134*c2c66affSColin Finck default:
135*c2c66affSColin Finck printf("\n ERROR: Unhandled dwWaitStatus.\n");
136*c2c66affSColin Finck ExitProcess(GetLastError());
137*c2c66affSColin Finck break;
138*c2c66affSColin Finck }
139*c2c66affSColin Finck }
140*c2c66affSColin Finck }
141*c2c66affSColin Finck
RefreshDirectory(LPTSTR lpDir)142*c2c66affSColin Finck void RefreshDirectory(LPTSTR lpDir)
143*c2c66affSColin Finck {
144*c2c66affSColin Finck // This is where you might place code to refresh your
145*c2c66affSColin Finck // directory listing, but not the subtree because it
146*c2c66affSColin Finck // would not be necessary.
147*c2c66affSColin Finck
148*c2c66affSColin Finck _tprintf(TEXT("Directory (%s) changed.\n"), lpDir);
149*c2c66affSColin Finck }
150*c2c66affSColin Finck
RefreshTree(LPTSTR lpDrive)151*c2c66affSColin Finck void RefreshTree(LPTSTR lpDrive)
152*c2c66affSColin Finck {
153*c2c66affSColin Finck // This is where you might place code to refresh your
154*c2c66affSColin Finck // directory listing, including the subtree.
155*c2c66affSColin Finck
156*c2c66affSColin Finck _tprintf(TEXT("Directory tree (%s) changed.\n"), lpDrive);
157*c2c66affSColin Finck }
158