//---------------------------------------------------------
void ofXMLSettings::removeTag(string  tag, int which){
	
	vector<string> tokens = tokenize(tag,":");
	
	//no tags so we return
	if( tokens.size() == 0 ) return;
		
	//grab the handle from the level we are at
	//normally this is the doc but could be a pushed node
	TiXmlHandle tagHandle = *storedHandle;
	
	if(which < 0) which = 0;
	
	for(int x=0;x<tokens.size();x++){
	
		//we only support multi tags
		//with same name at root level
		if(x > 0) which = 0;
			
		TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);
		
		if ( !isRealHandle.Node() ) break;
		else{
			if (x == tokens.size()-1){
				//if we are at the last tag and it exists 
				//we use its parent to remove it - haha
				tagHandle.ToNode()->RemoveChild( isRealHandle.ToNode() );
			}
			tagHandle = isRealHandle;
		}
	}
	
	tokens.clear();
}
Exemplo n.º 2
0
//---------------------------------------------------------
bool ofxXmlSettings::tagExists(const string& tag, int which){

	vector<string> tokens = tokenize(tag,":");

	bool found = false;

	//grab the handle from the level we are at
	//normally this is the doc but could be a pushed node
	TiXmlHandle tagHandle = storedHandle;

	if(which < 0) which = 0;

	for(int x=0;x<(int)tokens.size();x++){

		//we only support multi tags
		//with same name at root level
		if(x > 0) which = 0;

		TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);

		//as soon as we find a tag that doesn't exist
		//we return false;
		if ( !isRealHandle.ToNode() ){
			found = false;
			break;
		}
		else{
			found = true;
			tagHandle = isRealHandle;
		}
	}

	return found;
}
// This method adds an element to XML file
void CErrorReportExporter::AddElemToXML(CString sName, CString sValue, TiXmlNode* root)
{
	strconv_t strconv;
	TiXmlHandle hElem = new TiXmlElement(strconv.t2utf8(sName));
	root->LinkEndChild(hElem.ToNode());
	TiXmlText* text = new TiXmlText(strconv.t2utf8(sValue));
	hElem.ToElement()->LinkEndChild(text);
}
Exemplo n.º 4
0
void ofxFlashXFLBuilder :: pushTagAt( int i )
{
	TiXmlHandle isRealHandle = storedHandle.ChildElement( i );
	if( isRealHandle.ToNode() )
	{
		storedHandle = isRealHandle;
		level++;
	}
}
Exemplo n.º 5
0
BOOL CCrashInfoReader::AddFilesToCrashDescriptionXML(std::vector<FileItem> FilesToAdd)
{
  strconv_t strconv;

  TiXmlDocument doc;
  
  CString sFileName = g_CrashInfo.m_Reports[0].m_sErrorReportDirName + _T("\\crashrpt.xml");
  bool bLoad = doc.LoadFile(strconv.t2a(sFileName.GetBuffer(0)));
  if(!bLoad)
    return FALSE;

  TiXmlNode* root = doc.FirstChild("CrashRpt");
  if(!root)
    return FALSE;
  
  TiXmlHandle hFileItems = root->FirstChild("FileList");
  if(hFileItems.ToElement()==NULL)
  {
    hFileItems = new TiXmlElement("FileList");
    root->LinkEndChild(hFileItems.ToNode());
  }
  
  unsigned i;
  for(i=0; i<FilesToAdd.size(); i++)
  {    
    TiXmlHandle hFileItem = new TiXmlElement("FileItem");
    hFileItem.ToElement()->SetAttribute("name", strconv.t2utf8(FilesToAdd[i].m_sDestFile));
    hFileItem.ToElement()->SetAttribute("description", strconv.t2utf8(FilesToAdd[i].m_sDesc));
    hFileItems.ToElement()->LinkEndChild(hFileItem.ToNode());              

    m_Reports[0].m_FileItems[FilesToAdd[i].m_sDestFile] = FilesToAdd[i];
  }
  
  bool bSave = doc.SaveFile(); 
  if(!bSave)
    return FALSE;
  return TRUE;
}
Exemplo n.º 6
0
//---------------------------------------------------------
bool ofxXmlSettings::pushTag(const string&  tag, int which){

	int pos = tag.find(":");

    // Either find the tag specified, or the first tag if colon-seperated.
    string tagToFind((pos > 0) ? tag.substr(0,pos) :tag);

	//we only allow to push one tag at a time.
	TiXmlHandle isRealHandle = storedHandle.ChildElement(tagToFind, which);

	if( isRealHandle.ToNode() ){
		storedHandle = isRealHandle;
		level++;
		return true;
	}else{
        ofLogError("ofxXmlSettings") << "pushTag(): tag \"" << tag << "\" not found";
	}

	return false;
}
//---------------------------------------------------------
bool ofxXmlSettings::pushTag(const string&  tag, int which){

	int pos = tag.find(":");

    // Either find the tag specified, or the first tag if colon-seperated.
    string tagToFind((pos > 0) ? tag.substr(0,pos) :tag);
    
	//we only allow to push one tag at a time.
	TiXmlHandle isRealHandle = storedHandle.ChildElement(tagToFind, which);

	if( isRealHandle.ToNode() ){
		storedHandle = isRealHandle;
		level++;
		return true;
	}else{
		printf("pushTag - <");
		printf("%s",tag.c_str());
		printf("> tag not found\n");
	}

	return false;
}
Exemplo n.º 8
0
BOOL CCrashInfoReader::RemoveFilesFromCrashReport(int nReport, std::vector<CString> FilesToRemove)
{   
    strconv_t strconv;

    TiXmlDocument doc;

    CString sFileName = m_Reports[nReport].m_sErrorReportDirName + _T("\\crashrpt.xml");

    FILE* f = NULL; 
#if _MSC_VER<1400
    f = _tfopen(sFileName, _T("rb"));
#else
    _tfopen_s(&f, sFileName, _T("rb"));
#endif

    if(f==NULL)
    {    
        return FALSE;
    }

    bool bLoad = doc.LoadFile(f);  
    fclose(f);
    if(!bLoad)
    { 
        return FALSE;
    }

    TiXmlNode* root = doc.FirstChild("CrashRpt");
    if(!root)
    { 
        return FALSE;
    }

    TiXmlHandle hFileItems = root->FirstChild("FileList");
    if(hFileItems.ToElement()==NULL)
    {
        hFileItems = new TiXmlElement("FileList");
        root->LinkEndChild(hFileItems.ToNode());
    }

    unsigned i;
    for(i=0; i<FilesToRemove.size(); i++)
    { 
		std::map<CString, ERIFileItem>::iterator it = 
			m_Reports[nReport].m_FileItems.find(FilesToRemove[i]);
		if(it==m_Reports[nReport].m_FileItems.end())
            continue; // Such file item name does not exists, skip

		strconv_t strconv;
		TiXmlHandle hElem = hFileItems.ToElement()->FirstChild(strconv.t2a(FilesToRemove[i]));
		if(hElem.ToElement()!=NULL)
			hFileItems.ToElement()->RemoveChild(hElem.ToElement());              
		        
		if(it->second.m_bMakeCopy)
		{
			Utility::RecycleFile(it->second.m_sSrcFile, TRUE);
		}

		m_Reports[nReport].m_FileItems.erase(it);
    }

#if _MSC_VER<1400
    f = _tfopen(sFileName, _T("w"));
#else
    _tfopen_s(&f, sFileName, _T("w"));
#endif

    if(f==NULL)
        return FALSE;

    bool bSave = doc.SaveFile(f); 
    if(!bSave)
        return FALSE;
    fclose(f);
    return TRUE;
}
Exemplo n.º 9
0
BOOL CCrashInfoReader::AddFilesToCrashReport(int nReport, std::vector<ERIFileItem> FilesToAdd)
{   
    strconv_t strconv;

    TiXmlDocument doc;

    CString sFileName = m_Reports[nReport].m_sErrorReportDirName + _T("\\crashrpt.xml");

    FILE* f = NULL; 
#if _MSC_VER<1400
    f = _tfopen(sFileName, _T("rb"));
#else
    _tfopen_s(&f, sFileName, _T("rb"));
#endif

    if(f==NULL)
    {    
        return FALSE;
    }

    bool bLoad = doc.LoadFile(f);  
    fclose(f);
    if(!bLoad)
    { 
        return FALSE;
    }

    TiXmlNode* root = doc.FirstChild("CrashRpt");
    if(!root)
    { 
        return FALSE;
    }

    TiXmlHandle hFileItems = root->FirstChild("FileList");
    if(hFileItems.ToElement()==NULL)
    {
        hFileItems = new TiXmlElement("FileList");
        root->LinkEndChild(hFileItems.ToNode());
    }

    unsigned i;
    for(i=0; i<FilesToAdd.size(); i++)
    { 
        if(m_Reports[0].m_FileItems.find(FilesToAdd[i].m_sDestFile)!=m_Reports[0].m_FileItems.end())
            continue; // Such file item already exists, skip

        TiXmlHandle hFileItem = new TiXmlElement("FileItem");
        hFileItem.ToElement()->SetAttribute("name", strconv.t2utf8(FilesToAdd[i].m_sDestFile));
        hFileItem.ToElement()->SetAttribute("description", strconv.t2utf8(FilesToAdd[i].m_sDesc));
		if(FilesToAdd[i].m_bAllowDelete)
			hFileItem.ToElement()->SetAttribute("optional", "1");
        hFileItems.ToElement()->LinkEndChild(hFileItem.ToNode());              

        m_Reports[nReport].m_FileItems[FilesToAdd[i].m_sDestFile] = FilesToAdd[i];

		if(FilesToAdd[i].m_bMakeCopy)
		{
			CString sDestPath = m_Reports[nReport].m_sErrorReportDirName + _T("\\") + FilesToAdd[i].m_sDestFile;
			CopyFile(FilesToAdd[i].m_sSrcFile, sDestPath, TRUE);
			m_Reports[nReport].m_FileItems[FilesToAdd[i].m_sDestFile].m_sSrcFile = sDestPath;
		}
    }

#if _MSC_VER<1400
    f = _tfopen(sFileName, _T("w"));
#else
    _tfopen_s(&f, sFileName, _T("w"));
#endif

    if(f==NULL)
        return FALSE;

    bool bSave = doc.SaveFile(f); 
    if(!bSave)
        return FALSE;
    fclose(f);
    return TRUE;
}
//---------------------------------------------------------
int ofXMLSettings::writeTag(string  tag, char * valueStr, int which){
	
	vector<string> tokens = tokenize(tag,":");
	
	// allocate then clean up :
	TiXmlElement ** elements = new TiXmlElement*[tokens.size()];
	for(int x=0;x<tokens.size();x++){
		elements[x] = new TiXmlElement(tokens.at(x));
	}
	
	TiXmlText Value(valueStr);			
	
	// search our way up - do these tags exist?
	// find the first that DOESNT exist, then move backwards...
	TiXmlHandle tagHandle = *storedHandle;
	
	bool addNewTag = false;
	if(which == -1)addNewTag = true;
	
	for(int x=0;x<tokens.size();x++){
	
		if( x > 0 ){
			//multi tags of same name 
			//only for the root level
			which = 0;
			addNewTag = false;
		}
	
		TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);

		if ( !isRealHandle.Node() ||  addNewTag){
			
			for(int i=tokens.size()-1;i>=x;i--){
				if (i == tokens.size()-1){
					elements[i]->InsertEndChild(Value);
				} else {
					elements[i]->InsertEndChild(*(elements[i+1]));
				}
			}
						
			tagHandle.ToNode()->InsertEndChild(*(elements[x]));
			
			break;
			
		} else {
			 tagHandle = isRealHandle;
			 if (x == tokens.size()-1){
				// what we want to change : TiXmlHandle valHandle = tagHandle.Child( 0 );
				tagHandle.ToNode()->Clear();
				tagHandle.ToNode()->InsertEndChild(Value);
			}
		}
	}
	
	//lets find how many of the same tags exist
	//then we can return the numTags;
	int numSameTags = 0;
	while( (storedHandle->ChildElement( tokens.at(0), numSameTags )).Node() ){
		numSameTags++;
	}	
	
	//now, clear that vector! 
	tokens.clear();		

	return numSameTags;
}
Exemplo n.º 11
0
shared_ptr<Entity> EntityFactory::createEntity(const string& path)
{
    shared_ptr<Entity> entity(new Entity);
    shared_ptr<RenderJob> renderjob(new RenderJob());
    entity->setRenderJob(renderjob);

    TiXmlDocument entityfile(path);
    if (!entityfile.LoadFile()) { // If error when loading file.
        LOG(logERROR) << "Error when loading entity file " << path <<
        "\nError at line " << entityfile.ErrorRow() <<
        "\nError description: " << entityfile.ErrorDesc();
        throw EntityCreationError();
    }

    TiXmlHandle dochandle = TiXmlHandle(&entityfile).FirstChild("entity");

    // Set name and description.

    TiXmlElement* name_element = dochandle.FirstChild("name").ToElement();
    if (name_element)
        entity->setName(name_element->GetText());
    else
        LOG(logWARNING) << "No name element in entity file " << path;
    TiXmlElement* desc_element = dochandle.FirstChild("desc").ToElement();
    if (desc_element) {
        entity->setDesc(desc_element->GetText());
    }
    else {
        LOG(logWARNING) << "No desc element in entity file " << path;
    }

    /*
     * Load gfx.
     */

    // Textures are loaded to an array in the order they are declared. My shader
    // code assumes that the albedo texture is index 0 and the normal map in
    // index 1.
    TiXmlHandle texhandle = dochandle.FirstChild("gfx").FirstChild("textures");
    if (texhandle.ToNode()) { // If texture tag exists.
        vector<GLuint> created_textures;
        TiXmlElement* texture_element;
        int i = 0;
        while (texture_element = texhandle.ChildElement(i++).ToElement()) {
            string texname(texture_element->GetText());
            created_textures.push_back(Locator::getFileService().makeTexture(texname));
        }

        int num_textures = created_textures.size();

        if (num_textures > 0) {
            renderjob->m_textures = new GLuint[num_textures];
        }
        renderjob->m_num_textures = num_textures;;
        for (int i = 0; i < num_textures; i++) {
            renderjob->m_textures[i] = created_textures[i];
        }
    }


    // Load model and check number of materials.
    TiXmlElement* model_element =
        dochandle.FirstChild("gfx").FirstChild("model").ToElement();
    if (!model_element) {
        LOG(logERROR) << "No model element in entity file " << path;
        throw EntityCreationError();
    }
    string modelpath = "assets/models/" + string(model_element->GetText()) + ".obj";
    string absolute_path(Locator::getFileService().getRealPath(modelpath));
    ObjFile model(absolute_path);

    // Load shaders.
    bool materials_defined = false; // Needed to determine whether uniform blocks are created.
    {
        TiXmlElement* shader_defines_element =
            dochandle.FirstChild("gfx").FirstChild("shader_defines").ToElement();
        if (!shader_defines_element) {
            LOG(logERROR) << "No shader_defines element in entity file " << path;
            throw EntityCreationError();
        }
        set<string> defines;
        string shader_defines(shader_defines_element->GetText());
        // Tokenize shader_defines;
        typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
        boost::char_separator<char> comma(", ");
        tokenizer tokens(shader_defines, comma);
        foreach(string define, tokens) {
            defines.insert(define);
        }
        GLuint num_materials = model.getNumMaterials();
        string materials_define("MATERIALS");
        if (defines.find(materials_define) != defines.end()) { // If materials define found.
            materials_defined = true;
            defines.erase(materials_define);
            stringstream materials_define_stream;
            materials_define_stream << materials_define << " " << num_materials;
            defines.insert(materials_define_stream.str());
        }

        // Insert vertex attrib indices.
        int i = 0;
        foreach(const char* enum_name, renderjob_enums::vertex_strings) {
            defines.insert(makeDefineFromEnum(enum_name, i++));
        }
Exemplo n.º 12
0
//---------------------------------------------------------
int ofxXmlSettings::writeTag(const string&  tag, const string& valueStr, int which){

	vector<string> tokens = tokenize(tag,":");

	// allocate on the stack
    vector<TiXmlElement> elements;
    elements.reserve(tokens.size());
	for(int x=0;x<(int)tokens.size();x++)
        elements.push_back(tokens.at(x));


	TiXmlText Value(valueStr);

	// search our way up - do these tags exist?
	// find the first that DOESNT exist, then move backwards...
	TiXmlHandle tagHandle = storedHandle;

	bool addNewTag = false;
	if(which == -1)addNewTag = true;

	for(int x=0;x<(int)tokens.size();x++){

		if( x > 0 ){
			//multi tags of same name
			//only for the root level
			which = 0;
			addNewTag = false;
		}

		TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);

		if ( !isRealHandle.ToNode() ||  addNewTag){

			for(int i=(int)tokens.size()-1;i>=x;i--){
				if (i == (int)tokens.size()-1){
					elements[i].InsertEndChild(Value);
				} else {
					elements[i].InsertEndChild(elements[i+1]);
				}
			}

			tagHandle.ToNode()->InsertEndChild(elements[x]);

			break;

		} else {
			 tagHandle = isRealHandle;
			 if (x == (int)tokens.size()-1){
				// what we want to change : TiXmlHandle valHandle = tagHandle.Child( 0 );
				tagHandle.ToNode()->Clear();
				tagHandle.ToNode()->InsertEndChild(Value);
			}
		}
	}


	//lets count how many tags with our name exist so we can return an index

	//ripped from tinyXML as doing this ourselves once is a LOT! faster
	//than having this called n number of times in a while loop - we go from n*n iterations to n iterations
	int numSameTags;
	TiXmlElement* child = ( storedHandle.FirstChildElement( tokens.at(0) ) ).ToElement();
	for (numSameTags = 0; child; child = child->NextSiblingElement( tokens.at(0) ), ++numSameTags){
		//nothing
	}

	return numSameTags;
}
Exemplo n.º 13
0
// This method generates an XML file describing the crash
BOOL CErrorReportExporter::CreateCrashDescriptionXML(CErrorReportInfo& eri)
{
	BOOL bStatus = FALSE;
	ERIFileItem fi;
	CString sFileName = eri.GetErrorReportDirName() + _T("\\crashrpt.xml");
	CString sErrorMsg;
	strconv_t strconv;
	TiXmlDocument doc;
	FILE* f = NULL; 
	CString sNum;
	CString sCrashRptVer;
	CString sOSIs64Bit;
	CString sExceptionType;

	fi.m_bMakeCopy = false;
	fi.m_sDesc = _T("±ÀÀ£³ÌÐòÊôÐÔ¼¯");
	fi.m_sDestFile = _T("crashrpt.xml");
	fi.m_sSrcFile = sFileName;
	fi.m_sErrorStatus = sErrorMsg;  
	// Add this file to the list
	eri.AddFileItem(&fi);

	TiXmlNode* root = root = new TiXmlElement("CrashRpt");
	doc.LinkEndChild(root);  
	sCrashRptVer.Format(_T("%d"), CRASHRPT_VER);
	TiXmlHandle(root).ToElement()->SetAttribute("version", strconv.t2utf8(sCrashRptVer));

	TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", "" );
	doc.InsertBeforeChild(root, *decl);
	
	AddElemToXML(_T("CrashGUID"), eri.GetCrashGUID(), root);
	AddElemToXML(_T("AppName"), eri.GetAppName(), root);
	AddElemToXML(_T("AppVersion"), eri.GetAppVersion(), root);  
	AddElemToXML(_T("ImageName"), eri.GetImageName(), root);
	AddElemToXML(_T("OperatingSystem"), eri.GetOSName(), root);


	sOSIs64Bit.Format(_T("%d"), eri.IsOS64Bit());
	AddElemToXML(_T("OSIs64Bit"), sOSIs64Bit, root);

	AddElemToXML(_T("GeoLocation"), eri.GetGeoLocation(), root);
	AddElemToXML(_T("SystemTimeUTC"), eri.GetSystemTimeUTC(), root);
		
	if(eri.GetExceptionAddress()!=0)
	{
		sNum.Format(_T("0x%I64x"), eri.GetExceptionAddress());
		AddElemToXML(_T("ExceptionAddress"), sNum, root);

		AddElemToXML(_T("ExceptionModule"), eri.GetExceptionModule(), root);

		sNum.Format(_T("0x%I64x"), eri.GetExceptionModuleBase());
		AddElemToXML(_T("ExceptionModuleBase"), sNum, root);

		AddElemToXML(_T("ExceptionModuleVersion"), eri.GetExceptionModuleVersion(), root);
	}

	sExceptionType.Format(_T("%d"), m_CrashInfo.m_nExceptionType);
	AddElemToXML(_T("ExceptionType"), sExceptionType, root);
	if(m_CrashInfo.m_nExceptionType==CR_SEH_EXCEPTION)
	{
		CString sExceptionCode;
		sExceptionCode.Format(_T("%d"), m_CrashInfo.m_dwExceptionCode);
		AddElemToXML(_T("ExceptionCode"), sExceptionCode, root);
	}
	else if(m_CrashInfo.m_nExceptionType==CR_CPP_SIGFPE)
	{
		CString sFPESubcode;
		sFPESubcode.Format(_T("%d"), m_CrashInfo.m_uFPESubcode);
		AddElemToXML(_T("FPESubcode"), sFPESubcode, root);
	}
	else if(m_CrashInfo.m_nExceptionType==CR_CPP_INVALID_PARAMETER)
	{
		AddElemToXML(_T("InvParamExpression"), m_CrashInfo.m_sInvParamExpr, root);
		AddElemToXML(_T("InvParamFunction"), m_CrashInfo.m_sInvParamFunction, root);
		AddElemToXML(_T("InvParamFile"), m_CrashInfo.m_sInvParamFile, root);

		CString sInvParamLine;
		sInvParamLine.Format(_T("%d"), m_CrashInfo.m_uInvParamLine);
		AddElemToXML(_T("InvParamLine"), sInvParamLine, root);
	}

	CString sGuiResources;
	sGuiResources.Format(_T("%d"), eri.GetGuiResourceCount());
	AddElemToXML(_T("GUIResourceCount"), sGuiResources, root);

	CString sProcessHandleCount;
	sProcessHandleCount.Format(_T("%d"), eri.GetProcessHandleCount());
	AddElemToXML(_T("OpenHandleCount"), sProcessHandleCount, root);

	AddElemToXML(_T("MemoryUsageKbytes"), eri.GetMemUsage(), root);

	if(eri.GetScreenshotInfo().m_bValid)
	{
		TiXmlHandle hScreenshotInfo = new TiXmlElement("ScreenshotInfo");
		root->LinkEndChild(hScreenshotInfo.ToNode());

		TiXmlHandle hVirtualScreen = new TiXmlElement("VirtualScreen");    

		sNum.Format(_T("%d"), eri.GetScreenshotInfo().m_rcVirtualScreen.left);
		hVirtualScreen.ToElement()->SetAttribute("left", strconv.t2utf8(sNum));

		sNum.Format(_T("%d"), eri.GetScreenshotInfo().m_rcVirtualScreen.top);
		hVirtualScreen.ToElement()->SetAttribute("top", strconv.t2utf8(sNum));

		sNum.Format(_T("%d"), eri.GetScreenshotInfo().m_rcVirtualScreen.Width());
		hVirtualScreen.ToElement()->SetAttribute("width", strconv.t2utf8(sNum));

		sNum.Format(_T("%d"), eri.GetScreenshotInfo().m_rcVirtualScreen.Height());
		hVirtualScreen.ToElement()->SetAttribute("height", strconv.t2utf8(sNum));

		hScreenshotInfo.ToNode()->LinkEndChild(hVirtualScreen.ToNode());

		TiXmlHandle hMonitors = new TiXmlElement("Monitors");
		hScreenshotInfo.ToElement()->LinkEndChild(hMonitors.ToNode());                  

		size_t i;
		for(i=0; i<eri.GetScreenshotInfo().m_aMonitors.size(); i++)
		{ 
			MonitorInfo& mi = eri.GetScreenshotInfo().m_aMonitors[i];      
			TiXmlHandle hMonitor = new TiXmlElement("Monitor");

			sNum.Format(_T("%d"), mi.m_rcMonitor.left);
			hMonitor.ToElement()->SetAttribute("left", strconv.t2utf8(sNum));

			sNum.Format(_T("%d"), mi.m_rcMonitor.top);
			hMonitor.ToElement()->SetAttribute("top", strconv.t2utf8(sNum));

			sNum.Format(_T("%d"), mi.m_rcMonitor.Width());
			hMonitor.ToElement()->SetAttribute("width", strconv.t2utf8(sNum));

			sNum.Format(_T("%d"), mi.m_rcMonitor.Height());
			hMonitor.ToElement()->SetAttribute("height", strconv.t2utf8(sNum));

			hMonitor.ToElement()->SetAttribute("file", strconv.t2utf8(Utility::GetFileName(mi.m_sFileName)));

			hMonitors.ToElement()->LinkEndChild(hMonitor.ToNode());                  
		}

		TiXmlHandle hWindows = new TiXmlElement("Windows");
		hScreenshotInfo.ToElement()->LinkEndChild(hWindows.ToNode());                  

		for(i=0; i<eri.GetScreenshotInfo().m_aWindows.size(); i++)
		{ 
			WindowInfo& wi = eri.GetScreenshotInfo().m_aWindows[i];      
			TiXmlHandle hWindow = new TiXmlElement("Window");

			sNum.Format(_T("%d"), wi.m_rcWnd.left);
			hWindow.ToElement()->SetAttribute("left", strconv.t2utf8(sNum));

			sNum.Format(_T("%d"), wi.m_rcWnd.top);
			hWindow.ToElement()->SetAttribute("top", strconv.t2utf8(sNum));

			sNum.Format(_T("%d"), wi.m_rcWnd.Width());
			hWindow.ToElement()->SetAttribute("width", strconv.t2utf8(sNum));

			sNum.Format(_T("%d"), wi.m_rcWnd.Height());
			hWindow.ToElement()->SetAttribute("height", strconv.t2utf8(sNum));

			hWindow.ToElement()->SetAttribute("title", strconv.t2utf8(wi.m_sTitle));

			hWindows.ToElement()->LinkEndChild(hWindow.ToNode());                  
		}
	}

	TiXmlHandle hCustomProps = new TiXmlElement("CustomProps");
	root->LinkEndChild(hCustomProps.ToNode());

	int i;
	for(i=0; i<eri.GetPropCount(); i++)
	{ 
		CString sName;
		CString sVal;
		eri.GetPropByIndex(i, sName, sVal);

		TiXmlHandle hProp = new TiXmlElement("Prop");

		hProp.ToElement()->SetAttribute("name", strconv.t2utf8(sName));
		hProp.ToElement()->SetAttribute("value", strconv.t2utf8(sVal));

		hCustomProps.ToElement()->LinkEndChild(hProp.ToNode());                  
	}

	TiXmlHandle hFileItems = new TiXmlElement("FileList");
	root->LinkEndChild(hFileItems.ToNode());

	for(i=0; i<eri.GetFileItemCount(); i++)
	{    
		ERIFileItem* rfi = eri.GetFileItemByIndex(i);
		TiXmlHandle hFileItem = new TiXmlElement("FileItem");

		hFileItem.ToElement()->SetAttribute("name", strconv.t2utf8(rfi->m_sDestFile));
		hFileItem.ToElement()->SetAttribute("description", strconv.t2utf8(rfi->m_sDesc));
		if(rfi->m_bAllowDelete)
			hFileItem.ToElement()->SetAttribute("optional", "1");
		if(!rfi->m_sErrorStatus.IsEmpty())
			hFileItem.ToElement()->SetAttribute("error", strconv.t2utf8(rfi->m_sErrorStatus));

		hFileItems.ToElement()->LinkEndChild(hFileItem.ToNode());                  
	}

#if _MSC_VER<1400
	f = _tfopen(sFileName, _T("w"));
#else
	_tfopen_s(&f, sFileName, _T("w"));
#endif

	if(f==NULL)
	{
		sErrorMsg = _T("Error opening file for writing");
		goto cleanup;
	}

	doc.useMicrosoftBOM = true;
	bool bSave = doc.SaveFile(f); 
	if(!bSave)
	{
		sErrorMsg = doc.ErrorDesc();
		goto cleanup;
	}

	fclose(f);
	f = NULL;

	bStatus = TRUE;

cleanup:

	if(f)
		fclose(f);

	if(!bStatus)
	{
		eri.GetFileItemByName(fi.m_sDestFile)->m_sErrorStatus = sErrorMsg;
	}

	return bStatus;
}