void DirectoryMonitor::processNotification(const string& aPath, const ByteVector& aBuf) {
	char* pBase = (char*)&aBuf[0];
	string oldPath;

	for (;;)
	{
		FILE_NOTIFY_INFORMATION& fni = (FILE_NOTIFY_INFORMATION&)*pBase;

		string notifyPath(Text::fromT(tstring(fni.FileName, fni.FileNameLength / sizeof(wchar_t) )));

		// If it could be a short filename, expand it.
		auto fileName = Util::getFileName(notifyPath);

		// The maximum length of an 8.3 filename is twelve, including the dot.
		/*if (fileName.length() <= 12 && fileName.front() == _T('~')) {
			// Convert to the long filename form. Unfortunately, this
			// does not work for deletions, so it's an imperfect fix.
			wchar_t wbuf[UNC_MAX_PATH];
			if (::GetLongPathName(Text::toT(notifyPath).c_str(), wbuf, _countof (wbuf)) > 0)
				notifyPath = Text::fromT(wbuf);
		}*/

		notifyPath = aPath + notifyPath;
		switch(fni.Action) {
			case FILE_ACTION_ADDED: 
				// The file was added to the directory.
				fire(DirectoryMonitorListener::FileCreated(), notifyPath);
				break;
			case FILE_ACTION_REMOVED: 
				// The file was removed from the directory.
				fire(DirectoryMonitorListener::FileDeleted(), notifyPath);
				break;
			case FILE_ACTION_RENAMED_OLD_NAME: 
				// The file was renamed and this is the old name. 
				oldPath = notifyPath;
				break;
			case FILE_ACTION_RENAMED_NEW_NAME: 
				// The file was renamed and this is the new name.
				fire(DirectoryMonitorListener::FileRenamed(), oldPath, notifyPath);
				break;
			case FILE_ACTION_MODIFIED:
				fire(DirectoryMonitorListener::FileModified(), notifyPath);
				break;
		}

		if (!fni.NextEntryOffset)
			break;
		pBase += fni.NextEntryOffset;
	};
}
void DirectoryMonitor::processNotification(const string& aPath, const ByteVector& aBuf) {
	char* pBase = (char*)&aBuf[0];
	string oldPath;

	for (;;)
	{
		FILE_NOTIFY_INFORMATION& fni = (FILE_NOTIFY_INFORMATION&)*pBase;

		string notifyPath(Text::fromT(tstring(fni.FileName, fni.FileNameLength / sizeof(wchar_t) )));

		auto fileName = Util::getFileName(notifyPath);

		notifyPath = aPath + notifyPath;
		switch(fni.Action) {
			case FILE_ACTION_ADDED: 
				// The file was added to the directory.
				fire(DirectoryMonitorListener::FileCreated(), notifyPath);
				break;
			case FILE_ACTION_REMOVED: 
				// The file was removed from the directory.
				fire(DirectoryMonitorListener::FileDeleted(), notifyPath);
				break;
			case FILE_ACTION_RENAMED_OLD_NAME: 
				// The file was renamed and this is the old name. 
				oldPath = notifyPath;
				break;
			case FILE_ACTION_RENAMED_NEW_NAME: 
				// The file was renamed and this is the new name.
				fire(DirectoryMonitorListener::FileRenamed(), oldPath, notifyPath);
				break;
			case FILE_ACTION_MODIFIED:
				fire(DirectoryMonitorListener::FileModified(), notifyPath);
				break;
		}

		if (!fni.NextEntryOffset)
			break;
		pBase += fni.NextEntryOffset;
	};
}
bool PPSNotifyGroupManager::joinNotifyGroup(const std::string& path, std::string& groupId)
{
	std::string notifyFile;
	std::string notifyPath(path);
	std::size_t nPos = notifyPath.rfind('/');

	// Search through the directories in the string until we find a valid .notify object
	while (nPos != std::string::npos) {

		// Chop off everything after the last '/' to get the path without the PPS object name
		notifyPath = notifyPath.substr(0, nPos);

		// Do we already have a notify group for this path?
		const_groupIter it = m_notifyGroups.find(notifyPath);

		// We found a match!
		if (it != m_notifyGroups.end() && (*it).second != NULL) {

			groupId = (*it).second->getNotifyGroupId();
			return true;
		}

		// Add ".notify?wait" to the notify path, to make it a real file
		notifyFile = notifyPath + "/.notify?wait";

		// Try to open this .notify object
		int fd = ::open(notifyFile.c_str(), O_RDONLY);

		// This is the .notify object to use
		if (fd >= 0) {

			char data[20];
			int len = ::read(fd, data, sizeof(data) - 1);
			// Terminate string to remove the newline char
			data[len > 0 ? len - 1 : 0] = '\0';

			PPSNotifier* pNotifier = new PPSNotifier();
			pNotifier->setNotifyGroupId(std::string(data));
			pNotifier->setNotifyOjbPath(notifyPath);
			pNotifier->setObjFd(::dup(fd));
                        ::close(fd);

			// Add this badboy to our cache of notify groups
			m_notifyGroups.insert(groupValue(notifyPath, pNotifier));

			// Start the notify reading thread
			pNotifier->startNotifyLoop();

			groupId = pNotifier->getNotifyGroupId();
			return true;
		}
		// Keep looking
		else {

			nPos = notifyPath.rfind('/');
		}
	}

	// We didn't find a notify group
	groupId = "";
	return false;
}