//=============================================================================
bool CPdpManager::ProcessLine(const string& line )
{

	int pos = 0;
	std::string file = "";
	std::string group = "";
	bool unique = false;

	enum eCommand
	{
		kNone,
		kVersion,
		kProject,
		kFiles,
		kBootFile,
		kRunOpts,
		kGrouping,
		kWorkingDir,
		kRemotePath,
	}

	static currentCommand = kNone;
	
	FileList::iterator it;

	if( line != "" )
	{
	
		string sub = line.substr( 1, (line.size() - 1) );

		switch( line[0] )
		{	
		case '!':
			if( m_bFileIdentifierFound )
			{
				if( sub == "VERSION" )
				{
					currentCommand = kVersion;
				}
				else if( sub == "PROJECT" )
				{
					currentCommand = kProject;
				}
				else if( sub == "FILES" )
				{
					currentCommand = kFiles;
				}
				else if( sub == "BOOT_FILE" )
				{
					currentCommand = kBootFile;
				}
				else if( sub == "RUN_OPTS" )
				{
					currentCommand = kRunOpts;
				}
				else if( sub == "GROUPING" )
				{
					currentCommand = kGrouping;
				}
				else if( sub == "WORKING_DIR" )
				{
					currentCommand = kWorkingDir;
				}
				else if( sub == "REMOTE_PATH" )
				{
					currentCommand = kRemotePath;
				}
				else
				{
					dprintf("Invalid command: %s\n", line.c_str());
					return false;
				}
			}
			else
			{
				if( sub == "PAGE_DEBUGGER_PROJECT_FILE" )
				{
					m_bFileIdentifierFound = true;
					return true;
				}
				else
				{
					dprintf("Invalid file format (no PAGE_DEBUGGER_PROJECT_FILE directive)\n");
					return false;
				}
			}
			break;

		case '=':
			if( m_bFileIdentifierFound )
			{
				switch( currentCommand )
				{
				case kVersion:
					if( sub != Version() )
					{
						dprintf("Invalid file version\n");
						return false;
					}
					break;

				case kProject:
					m_strProjectName = sub;
					break;

				case kFiles:
				{
					m_FileList.push_back(SFile(sub));
					break;
				}

				case kBootFile:
					m_strBootFile = "";
					for( it = m_FileList.begin(); it != m_FileList.end(); ++it )
					{
						if( sub == (it->filename) )
						{
							m_strBootFile = sub;
							break;
						}
					}

					break;

				case kRunOpts:
					m_strRunOptions = sub;
					break;

				case kGrouping:
					pos = sub.find("->");
					file = sub.substr( 0, pos );
					group = sub.substr( (pos + 2), sub.size() );
					//m_GroupingMap[file] = group;
					SetFileGroup(file, group);

					/*unique = true;
					for( GroupList::iterator it = m_GroupList.begin(); it != m_GroupList.end(); ++it )
					{
						if( group == (*it) )
						{
							unique = false;
						}
					}

					if( unique )
					{
						m_GroupList.push_back( group );
					}*/
					
					break;
				case kWorkingDir:
					m_strWorkingDir = sub;
					break;

				case kRemotePath:
					m_strRemotePath = sub;
					break;

				default:
					dprintf("Invalid current command: %d\n", currentCommand);
					return false;
				}
			}
			else
			{
				dprintf("Value specified before command: %d\n", currentCommand);
				assert(0);
				return false;
			}
			break;

		case ';':
			currentCommand = kNone;
			break;

		default:
			dprintf("Invalid command character\n");
			return false;
		}

	}
		
	return true;

}
void CPdpManager::ProjStartElement(const char* name, const char** attrs)
{
	if (_stricmp(name, "options") == 0)
	{
		for (; *attrs; attrs += 2)
		{
			const char* attrName = attrs[0];
			const char* attrValue = attrs[1];
			
			if (_stricmp(attrName, "name") == 0)
			{
				m_strProjectName = attrValue;
			}			
			else if (_stricmp(attrName, "bootfile") == 0)
			{
				m_strBootFile = attrValue;
			}
			else if (_stricmp(attrName, "runargs") == 0)
			{
				m_strRunOptions = attrValue;
			}
			else if (_stricmp(attrName, "workdir") == 0)
			{
				m_strWorkingDir = attrValue;
			}
			else if (_stricmp(attrName, "remotepath") == 0)
			{
				m_strRemotePath = attrValue;
			}
		}
	}
	else if (_stricmp(name, "group") == 0)
	{
		for ( ; *attrs; attrs += 2)
		{
			const char* attrName = attrs[0];
			const char* attrValue = attrs[1];
			
			if (_stricmp(attrName, "name") == 0)
			{
				dprintf("loading group: %s\n", attrValue);
				
				if (strlen(attrValue) > 0)
				{
					string groupPath;
					for (vector<string>::iterator itr = vecGroupNameStack.begin(); itr != vecGroupNameStack.end(); itr++)
					{
						groupPath += *itr;
						groupPath += '/';
					}
					groupPath += attrValue;

					//store the 'path' to the group.
					m_GroupList.push_back(groupPath);				
					
					vecGroupStack.push_back(m_GroupList.size() - 1);
					vecGroupNameStack.push_back(attrValue);
				}
			}
		}
	}
	else if (_stricmp(name, "file") == 0)
	{
		for ( ; *attrs; attrs += 2)
		{
			const char* attrName = attrs[0];
			const char* attrValue = attrs[1];
			
			if (_stricmp(attrName, "path") == 0)
			{
				dprintf("loading file: %s\n", attrValue);
				if (vecGroupStack.size() > 0)
				{
					m_FileList.push_back(SFile(attrValue, vecGroupStack[vecGroupStack.size()-1]));
				}
				else
				{
					m_FileList.push_back(SFile(attrValue, -1));
				}
			}
		}
	}
}
SFile getFileMetadataWin( const std::string &path, bool with_usn )
{
	SFile ret;
	ret.name=path;
	WIN32_FILE_ATTRIBUTE_DATA fad;
	if( GetFileAttributesExW(ConvertToWchar(path).c_str(),  GetFileExInfoStandard, &fad) )
	{
		if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{
			ret.isdir=true;
		}
		LARGE_INTEGER size;
		size.HighPart = fad.nFileSizeHigh;
		size.LowPart = fad.nFileSizeLow;
		ret.size = size.QuadPart;

		LARGE_INTEGER lwt;
		lwt.HighPart = fad.ftLastWriteTime.dwHighDateTime;
		lwt.LowPart = fad.ftLastWriteTime.dwLowDateTime;

		ret.last_modified = os_windows_to_unix_time(lwt.QuadPart);

		lwt.HighPart=fad.ftCreationTime.dwHighDateTime;
		lwt.LowPart=fad.ftCreationTime.dwLowDateTime;

		ret.created=os_windows_to_unix_time(lwt.QuadPart);

		lwt.HighPart = fad.ftLastAccessTime.dwHighDateTime;
		lwt.LowPart = fad.ftLastAccessTime.dwLowDateTime;

		ret.accessed = os_windows_to_unix_time(lwt.QuadPart);

		if (fad.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
		{
			if (os_is_symlink_int(path))
			{
				ret.issym = true;
			}
			ret.isspecialf = true;
		}

		if(with_usn && !ret.isdir && !(fad.dwFileAttributes &FILE_ATTRIBUTE_REPARSE_POINT))
		{
			HANDLE hFile = CreateFileW(ConvertToWchar(path).c_str(), GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,
				OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

			if(hFile!=INVALID_HANDLE_VALUE)
			{
				std::vector<char> buffer;
				buffer.resize(1024);
				DWORD last_err=0;
				do 
				{
					DWORD ret_bytes = 0;
					BOOL b = DeviceIoControl(hFile, FSCTL_READ_FILE_USN_DATA, NULL, 0,
						buffer.data(), static_cast<DWORD>(buffer.size()), &ret_bytes, NULL);

					if(b)
					{
						USN_RECORD* usnv2=reinterpret_cast<USN_RECORD*>(buffer.data());
						if(usnv2->MajorVersion==2)
						{
							ret.usn = usnv2->Usn;
						}
						else if(usnv2->MajorVersion==3)
						{
							usn::USN_RECORD_V3* usnv3=reinterpret_cast<usn::USN_RECORD_V3*>(buffer.data());
							ret.usn = usnv3->Usn;
						}
						else
						{
							Log("USN entry major version "+convert(usnv2->MajorVersion)+" of file \""+path+"\" not supported", LL_ERROR);
						}
					}
					else
					{
						last_err=GetLastError();
					}

					if(last_err==ERROR_INSUFFICIENT_BUFFER)
					{
						buffer.resize(buffer.size()*2);
					}

				} while (last_err==ERROR_INSUFFICIENT_BUFFER);

				CloseHandle(hFile);
			}
		}

		return ret;
	}
	else
	{
		return SFile();
	}
}