Exemplo n.º 1
0
//  StopClipWatcher
//
void StopClipWatcher(ClipWatcher* watcher)
{
    if (watcher->notifier != INVALID_HANDLE_VALUE) {
        FindCloseChangeNotification(watcher->notifier);
        watcher->notifier = INVALID_HANDLE_VALUE;
    }
}
Exemplo n.º 2
0
static int
win32thr_del (struct win32thr *wth, struct event *ev)
{
    int i, n = --wth->n;

    if (ev->tq) timeout_del(ev);

    ev->wth = NULL;
    wth->evq->nevents--;

    i = ev->w.index;
    if (ev->flags & EVENT_SOCKET) {
	HANDLE hEvent = wth->handles[i];
	WSAEventSelect((int) ev->fd, hEvent, 0);
	CloseHandle(hEvent);
    }
    if (i < n) {
	ev = wth->events[n];
	ev->w.index = i;
	wth->events[i] = ev;
	wth->handles[i] = wth->handles[n];
    }
    wth->handles[n] = wth->signal;  /* lower signal event */

    if (ev->flags & EVENT_DIRWATCH)
	return !FindCloseChangeNotification(ev->fd);

    return 0;
}
Exemplo n.º 3
0
void TsubtitlesFile::done(void)
{
    Tsubtitles::done();
    if (hwatch) {
        FindCloseChangeNotification(hwatch);
    }
    hwatch = NULL;
}
Exemplo n.º 4
0
void UninitIni(void)
{
	if (!bModuleInitialized)
		return;

	CallService(MS_SYSTEM_REMOVEWAIT, (WPARAM)hIniChangeNotification, 0);
	FindCloseChangeNotification(hIniChangeNotification);
}
Exemplo n.º 5
0
BOOL CCheckFileNotificationsThread::DestroyHandles()
{
	FnDebugMessage("FN: starting to destroy handles");
	
	// Various tests
	ASSERT(m_lState==sStopping || m_lState==sTerminated || (m_lState==sInitializing && m_nHandles==0));

	if (m_pEventHandles==NULL)
		return TRUE;

	if (m_pReadDirectoryChangesW!=NULL)
	{
		ASSERT(m_pDirDatas[0]==NULL);
	

		// ReadDirectoryChangesW used, deleting DIRCHANGEDATA structures
		for (UINT n=1;n<m_nHandles;n++)
		{
			//Handle in event array and event in overlay structure should be same
			ASSERT(m_pEventHandles[n]==m_pDirDatas[n]->ol.hEvent);

			// Destructor of DIRCHANGEDATA closes ol.hEvent (i.e. handle in m_pEventHandles)
			delete m_pDirDatas[n];

			// Destructor also closes this handle
			//CloseHandle(pHandles[n]);

		}

		delete[] m_pDirDatas;
	}
	else
	{
		// Close change notifaction objects returned by FindFirstChangeNotifcation 
		// and free root directory string
		for (UINT n=1;n<m_nHandles;n++)
		{
			FindCloseChangeNotification(m_pEventHandles[n]);
			DebugCloseEvent(m_pEventHandles[n]);

			delete[] m_pRoots[n];
		}
		delete[] m_pRoots;
	}
	

	// Free event handle array
	delete[] m_pEventHandles;

	
	// Just for sure
	m_pEventHandles=NULL;
	m_pDirDatas=NULL;

	
	FnDebugMessage("FN: handles destroyed");
	return TRUE;
}
Exemplo n.º 6
0
DWORD WINAPI monitor_thread(VOID *p) {
    char watchme[PATH_MAX];
    HANDLE harr[2], fff;

    if(lock_engine()) {
	logg("^monitor_thread: failed to lock engine\n");
	return 0;
    }

    snprintf(watchme, sizeof(watchme), "%s\\forcerld", dbdir);
    watchme[sizeof(watchme)-1] = '\0';

    harr[0] = monitor_event;
    harr[1] = FindFirstChangeNotification(dbdir, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME);

    unlock_engine();

    if(harr[1] == INVALID_HANDLE_VALUE) {
	logg("^monitor_thread: failed to monitor directory changes on %s\n", dbdir);
	return 0;
    }

    logg("monitor_thread: watching directory changes on %s\n", dbdir);

    while(1) {
	WIN32_FIND_DATA wfd;
	SYSTEMTIME st;

	switch(WaitForMultipleObjects(2, harr, FALSE, INFINITE)) {
	case WAIT_OBJECT_0:
	    logg("*monitor_thread: terminating upon request\n");
	    FindCloseChangeNotification(harr[1]);
	    return 0;
	case WAIT_OBJECT_0 + 1:
	    break;
	default:
	    logg("*monitor_thread: unexpected wait failure - %u\n", GetLastError());
	    Sleep(1000);
	    continue;
	}
	FindNextChangeNotification(harr[1]);
	if((fff = FindFirstFile(watchme, &wfd)) == INVALID_HANDLE_VALUE)
	    continue;
	FindClose(fff);

	GetSystemTime(&st);
	SystemTimeToFileTime(&st, &wfd.ftCreationTime);
	if(CompareFileTime(&wfd.ftLastWriteTime, &wfd.ftCreationTime) > 0)
	    wfd.ftLastWriteTime = wfd.ftCreationTime;
	if(CompareFileTime(&wfd.ftLastWriteTime, &last_chk_time) <= 0)
	    continue;

	logg("monitor_thread: reload requested!\n");
	Scan_ReloadDatabase(minimal_definitions);
	GetSystemTime(&st);
	SystemTimeToFileTime(&st, &last_chk_time); /* FIXME: small race here */
    }
}
Exemplo n.º 7
0
DirectoryWinAPI::~DirectoryWinAPI()
{
	for(auto it = callbacks.begin(); it != callbacks.end(); ++it)
	{
		UnregisterWaitEx(it->second.waitHandle,  INVALID_HANDLE_VALUE);
		FindCloseChangeNotification(it->first);
		delete it->second.cb;
	}
}
Exemplo n.º 8
0
	void close()
	{
		if(handle!=INVALID_HANDLE_VALUE)
		{
			canceled = true;
			FindCloseChangeNotification(handle);
			handle=INVALID_HANDLE_VALUE;
		}
	}
Exemplo n.º 9
0
int WINAPI FileSysWatcher (LPVOID arg)
{
	HWND hDlg = (HWND)arg;
	LuaPerWindowInfo& info = LuaWindowInfo[hDlg];

	while(true)
	{
		char filename [1024], directory [1024];

		strncpy(filename, info.filename.c_str(), 1024);
		filename[1023] = 0;
		strcpy(directory, filename);
		char* slash = strrchr(directory, '/');
		slash = std::max(slash, strrchr(directory, '\\'));
		if(slash)
			*slash = 0;

		char* bar = strchr(filename, '|');
		if(bar) *bar = '\0';

		WIN32_FILE_ATTRIBUTE_DATA origData;
		GetFileAttributesEx (filename,  GetFileExInfoStandard,  (LPVOID)&origData);

		HANDLE hNotify = FindFirstChangeNotification(directory, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);

		if(hNotify)
		{
			DWORD dwWaitResult = WaitForSingleObject(hNotify, 500);

			if(dwWaitResult != STATUS_TIMEOUT)
			{
				if(dwWaitResult == WAIT_ABANDONED)
					return dwWaitResult;

				WIN32_FILE_ATTRIBUTE_DATA data;
				GetFileAttributesEx (filename,  GetFileExInfoStandard,  (LPVOID)&data);

				// at this point it could be any file in the directory that changed
				// so check to make sure it was the file we care about
				if(memcmp(&origData.ftLastWriteTime, &data.ftLastWriteTime, sizeof(FILETIME)))
				{
					RequestAbortLuaScript((int)hDlg, "terminated to reload the script");
					PostMessage(hDlg, WM_COMMAND, IDC_BUTTON_LUARUN, 0);
				}
			}

			//FindNextChangeNotification(hNotify); // let's not try to reuse it...
			FindCloseChangeNotification(hNotify); // but let's at least make sure to release it!
		}
		else
		{
			Sleep(500);
		}
	}

	return 0;
}
Exemplo n.º 10
0
	~DWEntry()
	{
		if(thread)
		{
			FindCloseChangeNotification(h);
			thread->disconnect(this);
			thread->wait();
			delete thread;
		}
	}
Exemplo n.º 11
0
DirChangeNotifier::~DirChangeNotifier() {
	m_fTerminate = true;
	if (m_hChangeDir != INVALID_HANDLE_VALUE)
		FindCloseChangeNotification(m_hChangeDir);

	if (m_hTask != 0) {
		WaitForSingleObject(m_hTask, INFINITE);
		CloseHandle(m_hTask);
	}
}
Exemplo n.º 12
0
TsubtitlesFile::~TsubtitlesFile()
{
    if (f != NULL) {
        fclose(f);
        f = NULL;
    }
    if (hwatch) {
        FindCloseChangeNotification(hwatch);
    }
}
Exemplo n.º 13
0
 WatchDirModifacationProcess::~WatchDirModifacationProcess(void)
 {
     if(m_fileHandle)
     {
         FindCloseChangeNotification(m_fileHandle);
     }
     if(m_closeHandle)
     {
         CloseHandle(m_closeHandle);
     }
 }
Exemplo n.º 14
0
void FilesystemChangesRunnable::stopWatching()
{
   // flag that we're not ready to process
   m_initialized = false;

   if ( m_dwChangeHandle != 0 )
   {
      FindCloseChangeNotification( m_dwChangeHandle );
      m_dwChangeHandle = 0;
   }
}
Exemplo n.º 15
0
BOOL EndWatchDir(LPVOID watchHand)
{
   // Stop directory watch
   BOOL ok = FALSE;
   pWatchInfo pInf = (pWatchInfo)watchHand;
   if (pInf)
   {
      ok = TerminateThread(pInf->hThread, 0);
      FindCloseChangeNotification(pInf->hChange);
   }
   return ok;
}
Exemplo n.º 16
0
void lua_script_unload(lua_State **L,HANDLE **lua_filenotify)
{
	lua_State *lua=*L;
	if(lua!=0){
		lua_close(lua);
		*L=0;
	}
	if(*lua_filenotify!=0){
		FindCloseChangeNotification(*lua_filenotify);
		*lua_filenotify=0;
	}
}
Exemplo n.º 17
0
	virtual DWORD Run()
	{
		SetThreadPriority(myHandle, THREAD_PRIORITY_IDLE);

		TCHAR aLocaleDir[1000];
		myMan->GetLocalizationBasePath(aLocaleDir, 1000);

		myMonitorHandle = FindFirstChangeNotification(
			aLocaleDir,
			FALSE,
			FILE_NOTIFY_CHANGE_LAST_WRITE);

		if ( myMonitorHandle == INVALID_HANDLE_VALUE)
			return 1;

		HANDLE aObjs[2] = { myMonitorHandle, myTerminateEvent };

		while (true)
		{
			DWORD aRes = WaitForMultipleObjects(2, aObjs, FALSE, INFINITE);

			if ( aRes == WAIT_FAILED)
				break;

			else if (aRes == WAIT_OBJECT_0 + 0)		//directory change
			{
				//HACK
				HWND aWnd = RootWindow::FindSingleInstance();

				if (aWnd == 0)
					break;
				//end HACK

				PostMessage(aWnd, RootWindow::WM_USER_LOADLOCALE, 0, 0);

				BOOL aRet = FindNextChangeNotification(myMonitorHandle);

				if (aRet == 0)
				{
					ATLTRACE("LocalizationDirectoryMonitorThread -- failed on FindNextChangeNotification, returning.\n");
					break;
				}
			}

			else if (aRes == WAIT_OBJECT_0 + 1)	//the terminate event occurred
				break;
		}

		FindCloseChangeNotification(myMonitorHandle);
		return 0;
	}
Exemplo n.º 18
0
DWORD __stdcall ChangeNotifyThread(LPVOID param)
{
	CoInitialize(NULL);

	CComQIPtr<IWebSite> site = (IWebSite*)param;

	CWebSite* pSite = ((CWebSite*)site.p);
	
	BSTR rootPath;
	site->get_rootPath(&rootPath);

	HANDLE m_hChangeHandle;

	m_hChangeHandle = FindFirstChangeNotification(_bstr_t(rootPath),
			TRUE,
			FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
			FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE
			);

	SysFreeString(rootPath);

	while (1)
	{
		DWORD nObject = MsgWaitForMultipleObjectsEx(
		  1,          // number of handles in handle array
		  &m_hChangeHandle,     // pointer to an object-handle array
		  INFINITE,  // time-out interval in milliseconds
		  QS_ALLEVENTS,      // type of input events to wait for
		  0         // wait flags
		);

		if (nObject == WAIT_OBJECT_0)
		{
			pSite->m_pRootDir->ScanFiles(TRUE, TRUE);
			pSite->Fire_FileTreeChanged();
		}
		else
		{
			break;
		}

		FindNextChangeNotification(m_hChangeHandle);
	}

	FindCloseChangeNotification(m_hChangeHandle);

	CoUninitialize();

	return 0;
}
Exemplo n.º 19
0
void WatcherData::stop()
{
    {
        std::lock_guard<std::mutex> locker(changeMutex);
        stopped = true;
        wakeup();
    }
    thread.join();

    for (HANDLE& h : changes) {
        FindCloseChangeNotification(h);
    }
    changes.clear();
}
Exemplo n.º 20
0
FILEMONITOR_PROC( void, EndMonitor )( PMONITOR monitor )
{
	if( !monitor )
		return;
	if( monitor->flags.bDispatched || monitor->flags.bScanning )
	{
		monitor->flags.bEnd = 1;
		return;
	}
	if( monitor->flags.bClosing )
	{
		if( l.flags.bLog ) Log( WIDE("Monitor already closing...") );
		return;
	}
	EnterCriticalSec( &monitor->cs );
	monitor->flags.bClosing = 1;
	monitor->flags.bRemoveFromEvents = 1;

	if( !monitor->flags.bRemovedFromEvents )
	{
		SetEvent( l.hMonitorThreadControlEvent );
		while( !monitor->flags.bRemovedFromEvents )
			Relinquish();
	}
	//Log1( WIDE("Closing the monitor on %s and killing thread...")
	//    , monitor->directory );
	if( monitor->hChange != INVALID_HANDLE_VALUE )
	{
		lprintf( WIDE( "close ntoification (wakes thread?" ) );
		FindCloseChangeNotification( monitor->hChange );
		lprintf( WIDE( "and then we wait..." ) );
	}
	monitor->hChange = INVALID_HANDLE_VALUE;
	{
		uint32_t tick = timeGetTime();
		while( monitor->pThread && ( ( tick+50 ) > timeGetTime() ) )
			Relinquish();
	}
	if( monitor->pThread )
	{
		EndThread( monitor->pThread );
	}
	//else
	//	Log( WIDE("Thread already left...") );
	CloseFileMonitors( monitor );
	RemoveTimer( monitor->timer );
	UnlinkThing( monitor );
	LeaveCriticalSec( &monitor->cs );
	Release( monitor );
}
Exemplo n.º 21
0
unsigned int __stdcall CMainWindow::WatcherThread( LPVOID lpvParam )
{
    CMainWindow * pThis = (CMainWindow*)lpvParam;

    DWORD dwWaitStatus;
    HANDLE dwChangeHandle;
    std::wstring monitorPath;

    while (pThis->threadRunning)
    {
        monitorPath = pThis->wpPath;
        // Watch the directory for file creation and deletion.
        std::wstring dirPath = monitorPath.substr(0, monitorPath.find_last_of('\\'));
        dwChangeHandle = FindFirstChangeNotification(
            dirPath.c_str(),
            FALSE,
            FILE_NOTIFY_CHANGE_LAST_WRITE);

        if (dwChangeHandle != INVALID_HANDLE_VALUE)
        {
            // Change notification is set.
            while ((pThis->threadRunning)&&(monitorPath.compare(pThis->wpPath) == 0))
            {
                // Wait for notification.
                dwWaitStatus = WaitForSingleObject(dwChangeHandle, 1000);

                switch (dwWaitStatus)
                {
                case WAIT_OBJECT_0:
                    SendMessage(*pThis, WM_SETTINGCHANGE, 0, 0);
                    break;

                case WAIT_TIMEOUT:
                    // A timeout occurred
                    if (monitorPath.compare(pThis->wpPath) != 0)
                    {
                        SendMessage(*pThis, WM_SETTINGCHANGE, 0, 0);
                    }
                    break;
                }
                FindNextChangeNotification(dwChangeHandle);
            }
            FindCloseChangeNotification(dwChangeHandle);
            monitorPath.clear();
        }
        Sleep(10);
    }
    return 0;
}
Exemplo n.º 22
0
void WatcherData::updatePaths()
{
    // printf("updating paths...\n");
    {
        std::lock_guard<std::mutex> updateLocker(updateMutex);
        handleToPath.clear();
        pathToHandle.clear();
        pathData.clear();
    }
    for (HANDLE& h : changes) {
        //printf("closing %d\n", h);
        FindCloseChangeNotification(h);
    }
    changes.clear();

    std::lock_guard<std::mutex> locker(changeMutex);
    for(const Path& path : paths) {
#ifdef HAVE_CYGWIN
        const ssize_t len = cygwin_conv_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, path.constData(), 0, 0);
        //printf("win path size %d\n", len);
        String winPath(len, '\0');
        cygwin_conv_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, path.constData(), winPath.data(), winPath.size());
        //printf("hello %s\n", winPath.constData());
        const HANDLE h = FindFirstChangeNotification(winPath.constData(), TRUE,
                                                     FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE);
#else
        const HANDLE h = FindFirstChangeNotification(path.constData(), TRUE,
                                                     FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE);
#endif
        if (h == INVALID_HANDLE_VALUE) {
            fprintf(stderr, "Unable to watch: %lu (%s)\n",
                    static_cast<unsigned long>(GetLastError()), path.constData());
        } else {
            changes.push_back(h);

            std::lock_guard<std::mutex> updateLocker(updateMutex);
            handleToPath[h] = path;
            pathToHandle[path] = h;
            PathData& data = pathData[path];
            path.visit([&data](const Path &p) {
                    if (p.isFile()) {
                        data.modified[p] = p.lastModifiedMs();
                        return Path::Continue;
                    }
                    return Path::Recurse;
                });
        }
    }
}
Exemplo n.º 23
0
void FreeDialogCache(void)
{
	if (hFileChange != INVALID_HANDLE_VALUE) {
		CallService(MS_SYSTEM_REMOVEWAIT, (WPARAM)hFileChange, 0);
		FindCloseChangeNotification(hFileChange);
	}
	DestroyServiceFunction(hServiceFileChange);

	DeleteCriticalSection(&csDialogCache);
	for (int i = 0; i < dialogCacheCount; i++)
		FreeDialogCacheEntry(&dialogCache[i]);
	dialogCacheCount = 0;
	mir_free(dialogCache); // does NULL check
	dialogCache = NULL;
}
Exemplo n.º 24
0
void winhostext_CleanUp() {
	for (int i=0; i< _SIZE; i++) {
		if (filesInfo[i] != NULL)
			deleteFileInfoOnPos(i);

		if(notifyHandles[i] != NULL) {
			FindCloseChangeNotification (notifyHandles[i]->notifyHandle);
			free((void*)notifyHandles[i]->dir);
			free((void*)notifyHandles[i]);
		}
			
	}

	free((void*)directoryQueryString);
	free((void*)baseDirectoryPath);
}
Exemplo n.º 25
0
QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
{
    if (handles.isEmpty())
        return;

    stop();
    wait();

    CloseHandle(handles.at(0));
    handles[0] = INVALID_HANDLE_VALUE;

    foreach (HANDLE h, handles) {
        if (h == INVALID_HANDLE_VALUE)
            continue;
        FindCloseChangeNotification(h);
    }
}
Exemplo n.º 26
0
void FileChangeWatcher::Shutdown()
{

    if (m_thread != NULL)
    {
        EndThread();
        m_thread = NULL;
    }

    if (m_handle != NULL)
    {
        FindCloseChangeNotification(m_handle);
        m_handle = NULL;
    }

    CloseHandle(m_threadEndEvent);
    m_threadEndEvent = NULL;

}
Exemplo n.º 27
0
void FileChangeWatcher::SetFile(const wxFileName& fileName)
{

    // If the file is in the same directory, we don't need to update anything.
    bool sameDirectory = (fileName.GetPath() == m_fileName.GetPath());

    m_fileName = fileName;
    UpdateFileAttributes();

    if (!sameDirectory || m_handle == NULL)
    {

        if (m_thread != NULL)
        {
            EndThread();
        }

        if (m_handle != NULL)
        {
            FindCloseChangeNotification(m_handle);
            m_handle = NULL;
        }

        m_handle = FindFirstChangeNotification(m_fileName.GetPath(), FALSE, FILE_NOTIFY_CHANGE_ATTRIBUTES);

        // Sometimes the return is NULL and sometimes it's INVALID_HANDLE_VALUE
        // in error conditions.
        if (m_handle == INVALID_HANDLE_VALUE)
        {
            m_handle = NULL;
        }

        if (m_handle != NULL)
        {
            DWORD threadId;
            m_thread = CreateThread(NULL, 0, ThreadProc, this, 0, &threadId);
        }
    
    }

}
Exemplo n.º 28
0
unsigned int WINAPI DirChangeNotifier::task() {
	m_hChangeDir = FindFirstChangeNotification(
		m_path,                        // directory to watch
		FALSE,                         // do not watch subtree
		FILE_NOTIFY_CHANGE_FILE_NAME); // watch for file names

	if (m_hChangeDir == INVALID_HANDLE_VALUE) {
		OutputDebugStringW(L"ERROR: FindFirstChangeNotification");
		_endthreadex(0);
		return 0;
	}

	while (TRUE) {
		DWORD dwWaitStatus = WaitForSingleObject(m_hChangeDir, INFINITE);
		if (dwWaitStatus == WAIT_OBJECT_0) {
			if (m_fTerminate) {
				break;
			}
			// A file was created, renamed, or deleted in the directory.
			// Refresh this directory and restart the notification.
			if (isChecked()) {
				::Info.AdvControl(&MainGuid, ACTL_SYNCHRO, 0, (void*)m_hPanel);
			}

			if (!FindNextChangeNotification(m_hChangeDir)) {
				OutputDebugStringW(L"ERROR: FindNextChangeNotification");
				break;
			}
		}
		else {
			OutputDebugStringW(L"WaitForSingleObject");
			break;
		}
	}
	if (!m_fTerminate)
		FindCloseChangeNotification(m_hChangeDir);
	m_hChangeDir = INVALID_HANDLE_VALUE;
	_endthreadex(0);
	return 0;
}
Exemplo n.º 29
0
void RegesterFolderAndFileDetect()
{
    HANDLE notify = FindFirstChangeNotification(
        L"D:\\test", TRUE,
        FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES |
        FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE);

    if (notify == INVALID_HANDLE_VALUE)
    {
        assert(notify);
        return;
    }

    while(1)
    {
        WaitForSingleObject(notify, INFINITE);
        OutputDebugString(L"目录有改变\n");
        FindNextChangeNotification(notify);
    }

    FindCloseChangeNotification(notify);

}
Exemplo n.º 30
0
DWORD WINAPI ChangeNotifyThread(NOTIFY_DATA *pnd)
{
	HANDLE hChange;
	DWORD  dwResult;
	TCHAR  szDirectory[MAX_PATH];

	lstrcpy(szDirectory, pnd->szFile);

	// get the directory name from filename
	if(GetFileAttributes(szDirectory) != FILE_ATTRIBUTE_DIRECTORY)
	{
		TCHAR *slash = _tcsrchr(szDirectory, _T('\\'));
		if(slash) *slash = '\0';
	}
	
	// watch the specified directory for changes
	hChange = FindFirstChangeNotification(szDirectory, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);

	do
	{
		HANDLE hEventList[2] = { hChange, pnd->hQuitEvent };
		
		if((dwResult = WaitForMultipleObjects(1, hEventList, FALSE, INFINITE)) == WAIT_OBJECT_0)
		{
			PostMessage(pnd->hwndNotify, pnd->uMsg, 0, (LPARAM)pnd);
		}

		FindNextChangeNotification(hChange);
	} 
	while(dwResult == WAIT_OBJECT_0);

	// cleanup
	FindCloseChangeNotification(hChange);
	free(pnd);

	return 0;
}