Source

NPAPI-chrome-file-api / Win / FileWatcherTaskWin.cpp

Full commit
ryanackley cf0cb11 




















unknown f8d99d0 




unknown 53b9d85 

unknown f8d99d0 
unknown 53b9d85 

unknown f8d99d0 


unknown 53b9d85 





unknown f8d99d0 



unknown 53b9d85 
unknown f8d99d0 
unknown 53b9d85 









unknown f8d99d0 
unknown 53b9d85 







unknown f8d99d0 
unknown 53b9d85 














unknown f8d99d0 
unknown 53b9d85 


unknown f8d99d0 
unknown 53b9d85 











unknown f8d99d0 


unknown 53b9d85 
unknown f8d99d0 
unknown 53b9d85 





unknown f8d99d0 
unknown 53b9d85 

unknown f8d99d0 

unknown 53b9d85 
unknown f8d99d0 
unknown 53b9d85 



/*
* Copyright 2012 Ryan Ackley (ryanackley@gmail.com)
*
* This file is part of NPAPI Chrome File API
*
* NPAPI Chrome File API is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <string>
#include "FileWatcherTaskWin.h"
#include "variant_list.h"



FileWatcherTaskWin::FileWatcherTaskWin(std::string path, FB::JSObjectPtr callback)
{
	stop = false;

	WCHAR widePathBuf[2048];
	int wpBufSize = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, widePathBuf, 2048);
	
	m_path = widePathBuf;
	m_callback = callback;

	ZeroMemory(&m_ol, sizeof(m_ol));

	m_handle = CreateFile(m_path.c_str(), 
								FILE_LIST_DIRECTORY, 
								FILE_SHARE_READ | FILE_SHARE_WRITE,
								NULL,
								OPEN_EXISTING,
								FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
								NULL);
	m_ol.hEvent = this;
}
void FileWatcherTaskWin::StartWatching()
{
	m_thread = boost::thread(boost::bind(&FileWatcherTaskWin::StartAlertLoop, this));
	QueueUserAPC(FileWatcherTaskWin::InitDirectoryWatcher, m_thread.native_handle(), (ULONG_PTR)this);
}
void FileWatcherTaskWin::StartAlertLoop()
{
	while (!stop)
	{
		SleepEx(INFINITE, TRUE);
	}
}
void CALLBACK FileWatcherTaskWin::InitDirectoryWatcher(ULONG_PTR arg)
{
	FileWatcherTaskWin* task = (FileWatcherTaskWin*)arg;
	BOOL success = task->ListenForFileEvents();
}

BOOL FileWatcherTaskWin::ListenForFileEvents()
{
	DWORD dwBytes=0;

	return ReadDirectoryChangesW(m_handle, m_buffer, 4096, TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytes, &m_ol, &WatcherCallback);
}

void CALLBACK FileWatcherTaskWin::WatcherCallback(DWORD dwErrorCode,DWORD bytesInBuf,LPOVERLAPPED lpOverlapped)
{
	FileWatcherTaskWin* task = (FileWatcherTaskWin*)lpOverlapped->hEvent; 
	if (bytesInBuf > 0)
	{
		BOOL moreToRead = true;
		char* readFrom = task->m_buffer;
		while(moreToRead)
		{
			FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)readFrom;
			std::wstring fileName(fni->FileName, fni->FileNameLength/sizeof(WCHAR));
			std::wstring wideFinalPath = task->m_path + L"\\" + fileName;

			char utf8Buf[2048];
			int pathLength = WideCharToMultiByte(CP_UTF8, 0, wideFinalPath.c_str(), -1, utf8Buf, 2048, NULL, NULL);
			std::string finalPath = utf8Buf;
			
			task->m_callback->Invoke("", FB::variant_list_of(finalPath));
			if (!fni->NextEntryOffset)
			{
				moreToRead = false;
			}
			else
			{
				readFrom += fni->NextEntryOffset;
			}
		}
	}
	BOOL success = task->ListenForFileEvents();
}
void CALLBACK FileWatcherTaskWin::TerminateWatch(ULONG_PTR arg)
{
	FileWatcherTaskWin* task = (FileWatcherTaskWin*)arg;
	task->CloseHandlesStopAlertLoop();
}
void FileWatcherTaskWin::CloseHandlesStopAlertLoop()
{
	CancelIo(m_handle);
	CloseHandle(m_handle);
	this->stop = true;
}
void FileWatcherTaskWin::StopWatching()
{
	QueueUserAPC(FileWatcherTaskWin::TerminateWatch, m_thread.native_handle(), (ULONG_PTR)this);
	// 5 seconds should be plenty of time
	m_thread.timed_join(boost::posix_time::seconds(5));
}