6
6
#include " debugutil.h"
7
7
#include " AppOfflineTrackingApplication.h"
8
8
#include " exceptions.h"
9
+ #include < EventLog.h>
9
10
10
11
FILE_WATCHER::FILE_WATCHER () :
11
12
m_hCompletionPort(NULL ),
12
13
m_hChangeNotificationThread(NULL ),
13
14
m_fThreadExit(FALSE ),
14
- _fTrackDllChanges(FALSE )
15
+ _fTrackDllChanges(FALSE ),
16
+ m_copied(false )
15
17
{
18
+ m_pShutdownEvent = CreateEvent (
19
+ nullptr , // default security attributes
20
+ TRUE , // manual reset event
21
+ FALSE , // not set
22
+ nullptr ); // name
16
23
}
17
24
18
25
FILE_WATCHER::~FILE_WATCHER ()
19
26
{
20
27
StopMonitor ();
21
- WaitForMonitor (20 );
28
+ WaitForMonitor (20000 );
22
29
}
23
30
24
31
void FILE_WATCHER::WaitForMonitor (DWORD dwRetryCounter)
@@ -60,7 +67,7 @@ FILE_WATCHER::Create(
60
67
_In_ PCWSTR pszFileNameToMonitor,
61
68
_In_ bool fTrackDllChanges ,
62
69
_In_ std::wstring shadowCopyPath,
63
- _In_ AppOfflineTrackingApplication * pApplication
70
+ _In_ AppOfflineTrackingApplication* pApplication
64
71
)
65
72
{
66
73
_shadowCopyPath = shadowCopyPath;
@@ -138,10 +145,10 @@ Win32 error
138
145
139
146
--*/
140
147
{
141
- FILE_WATCHER * pFileMonitor;
148
+ FILE_WATCHER* pFileMonitor;
142
149
BOOL fSuccess = FALSE ;
143
150
DWORD cbCompletion = 0 ;
144
- OVERLAPPED * pOverlapped = NULL ;
151
+ OVERLAPPED* pOverlapped = NULL ;
145
152
DWORD dwErrorStatus;
146
153
ULONG_PTR completionKey;
147
154
@@ -185,7 +192,15 @@ Win32 error
185
192
186
193
pFileMonitor->m_fThreadExit = TRUE ;
187
194
195
+ // TODO check instead for if a dll was changed here
196
+ if (pFileMonitor->_fTrackDllChanges )
197
+ {
198
+ pFileMonitor->m_Timer .CancelTimer ();
199
+ FILE_WATCHER::CopyAndShutdown (pFileMonitor);
200
+ }
201
+
188
202
LOG_INFO (L" Stopping file watcher thread" );
203
+
189
204
ExitThread (0 );
190
205
}
191
206
@@ -265,6 +280,7 @@ HRESULT
265
280
if (_fTrackDllChanges && notificationPath.extension ().compare (L" .dll" ) == 0 )
266
281
{
267
282
fFileChanged = TRUE ;
283
+ _fDllHadChanged = true ;
268
284
fDllChanged = TRUE ;
269
285
}
270
286
@@ -288,21 +304,72 @@ HRESULT
288
304
{
289
305
// Reference application before
290
306
_pApplication->ReferenceApplication ();
291
- if (fDllChanged )
307
+ if (fDllChanged || _fTrackDllChanges )
292
308
{
293
- // wait for all file changes to complete
294
- PostQueuedCompletionStatus (m_hCompletionPort, 0 , FILE_WATCHER_SHUTDOWN_KEY, NULL );
295
- WaitForMonitor (100 ); // 5 seconds here.
296
-
297
- // Copy contents before shutdown
298
- RETURN_IF_FAILED (Environment::CopyToDirectory (_shadowCopyPath, _strDirectoryName.QueryStr (), false ));
309
+ // Call shutdown later.
310
+ m_Timer.CancelTimer ();
311
+ m_Timer.InitializeTimer (FILE_WATCHER::TimerCallback, this , 5000 , 3000 );
312
+ }
313
+ else
314
+ {
315
+ RETURN_LAST_ERROR_IF (!QueueUserWorkItem (RunNotificationCallback, _pApplication.get (), WT_EXECUTEDEFAULT));
299
316
}
300
- RETURN_LAST_ERROR_IF (!QueueUserWorkItem (RunNotificationCallback, _pApplication.get (), WT_EXECUTEDEFAULT));
301
317
}
302
318
303
319
return S_OK;
304
320
}
305
321
322
+
323
+ VOID
324
+ CALLBACK
325
+ FILE_WATCHER::TimerCallback (
326
+ _In_ PTP_CALLBACK_INSTANCE Instance,
327
+ _In_ PVOID Context,
328
+ _In_ PTP_TIMER Timer
329
+ )
330
+ {
331
+ // Need to lock here.
332
+ Instance;
333
+ Timer;
334
+ CopyAndShutdown ((FILE_WATCHER*)Context);
335
+ }
336
+
337
+ DWORD WINAPI FILE_WATCHER::CopyAndShutdown (LPVOID arg)
338
+ {
339
+ EventLog::Error (
340
+ 1 ,
341
+ L" Callback" );
342
+ auto directoryName = 0 ;
343
+ // wrong path.
344
+ auto watcher = (FILE_WATCHER*)arg;
345
+ SRWExclusiveLock lock (watcher->m_copyLock );
346
+
347
+ if (watcher->m_copied )
348
+ {
349
+ return 0 ;
350
+ }
351
+
352
+ watcher->m_copied = true ;
353
+
354
+ auto dir = std::filesystem::path (watcher->_shadowCopyPath );
355
+ auto parent = dir.parent_path ();
356
+ directoryName = std::stoi (dir.filename ().string ());
357
+
358
+ directoryName++;
359
+ auto dirNameStr = std::to_wstring (directoryName);
360
+ auto destination = parent / dirNameStr.c_str ();
361
+
362
+ // Copy contents before shutdown
363
+ Environment::CopyToDirectory (destination, watcher->_strDirectoryName .QueryStr (), false );
364
+
365
+ watcher->_pApplication ->ReferenceApplication ();
366
+ SetEvent (watcher->m_pShutdownEvent );
367
+
368
+ QueueUserWorkItem (RunNotificationCallback, watcher->_pApplication .get (), WT_EXECUTEDEFAULT);
369
+ return 0 ;
370
+ }
371
+
372
+
306
373
DWORD
307
374
WINAPI
308
375
FILE_WATCHER::RunNotificationCallback (
@@ -311,7 +378,6 @@ FILE_WATCHER::RunNotificationCallback(
311
378
{
312
379
// Recapture application instance into unique_ptr
313
380
auto pApplication = std::unique_ptr<AppOfflineTrackingApplication, IAPPLICATION_DELETER>(static_cast <AppOfflineTrackingApplication*>(pvArg));
314
- DBG_ASSERT (pFileMonitor != NULL );
315
381
pApplication->OnAppOffline ();
316
382
317
383
return 0 ;
@@ -359,6 +425,10 @@ FILE_WATCHER::StopMonitor()
359
425
InterlockedExchange (&_lStopMonitorCalled, 1 );
360
426
// signal the file watch thread to exit
361
427
PostQueuedCompletionStatus (m_hCompletionPort, 0 , FILE_WATCHER_SHUTDOWN_KEY, NULL );
428
+ WaitForMonitor (20000 );
429
+ // See if this waits.
430
+ WaitForSingleObject (m_pShutdownEvent, 120000 );
431
+
362
432
// Release application reference
363
433
_pApplication.reset (nullptr );
364
434
}
0 commit comments