VFolder* VRIAServerSolution::RetainFolder() const
{
	VFolder *folder = NULL;

	if (fDesignSolution != NULL)
	{
		VProjectItem *item = fDesignSolution->GetSolutionFileProjectItem();
		if (item != NULL)
		{
			VFilePath path;
			item->GetFilePath( path);
			path = path.ToFolder();
			if (path.IsFolder())
			{
				folder = new VFolder( path);
				if (folder != NULL && !folder->Exists())
				{
					folder->Release();
					folder = NULL;
				}
			}
		}
	}	
	return folder;
}
VFile *VProcess::RetainFile( EFolderKind inPrimarySelector, const VString& inFileName, EFolderKind inSecondarySelector) const
{
	VFile *file = NULL;

	VFolder *parent = RetainFolder( inPrimarySelector);
	if (testAssert( parent != NULL))
	{
		file = new VFile( *parent, inFileName);
		if ( (file != NULL) && !file->Exists())
			ReleaseRefCountable( &file);
	}
	ReleaseRefCountable( &parent);

	if ( (file == NULL) && (inSecondarySelector != 0) )
	{
		parent = RetainFolder( inSecondarySelector);
		if ( (parent != NULL) && parent->Exists())
		{
			file = new VFile( *parent, inFileName);
			if ( (file != NULL) && !file->Exists())
				ReleaseRefCountable( &file);
		}
		ReleaseRefCountable( &parent);
	}
	
	return file;
}
VError VProjectItemFolder::_MoveTo(const VFolder& srcFolder, VFolder& destFolder)
{
	VError err = VE_OK;

	if (!destFolder.Exists())
		err = destFolder.CreateRecursive();
	else
		err = VE_UNKNOWN_ERROR; // TO DO ce n'est pas vrai : mais c'est pour le moment : 011008
								// que faire : ecraser, fusionner, on attends les specs !

	if (err == VE_OK)
		{
			for (VFolderIterator it_folder(&srcFolder, FI_WANT_FOLDERS | FI_WANT_INVISIBLES); it_folder.IsValid() && err == VE_OK; ++it_folder)
			{
				VFolder srcNewFolder(it_folder.Current()->GetPath());

				VString srcNewFolderName;
				srcNewFolder.GetName(srcNewFolderName);
				VString destNewFolderPath;
				destFolder.GetPath(destNewFolderPath);
				destNewFolderPath += srcNewFolderName;
				destNewFolderPath += FOLDER_SEPARATOR;
				VFolder destNewFolder(destNewFolderPath);

				err = _MoveTo(srcNewFolder, destNewFolder);
			}

			for (VFileIterator it_file(&srcFolder, FI_WANT_FILES | FI_WANT_INVISIBLES); it_file.IsValid() && err == VE_OK; ++it_file)
			{
				VFile srcNewFile(it_file.Current()->GetPath());

				VString srcNewFileName;
				srcNewFile.GetName(srcNewFileName);
				VString destNewFilePath;
				destFolder.GetPath(destNewFilePath);
				destNewFilePath += srcNewFileName;
				VFile destNewFile(destNewFilePath);

				VProjectItemFile projectItemFile;
				VURL srcURL = VURL(srcNewFile.GetPath());
				VURL destURL = VURL(destNewFile.GetPath());
				projectItemFile.MoveTo(srcURL, destURL);
			}
		}

	if (err == VE_OK)
	{
		err = srcFolder.Delete(true);
	}

	return err;
}
VFolder* VRIAServerSolution::RetainLogFolder( bool inCreateIfNotExists) const
{
	VFolder *folder = NULL;

	if (fDesignSolution != NULL)
	{
		VProjectItem *item = fDesignSolution->GetSolutionFileProjectItem();
		if (item != NULL)
		{
			VFilePath path;
			item->GetFilePath( path);
			path = path.ToFolder();
			path.ToSubFolder( L"Logs");
			folder = new VFolder( path);
			if (folder != NULL && !folder->Exists() && inCreateIfNotExists)
				folder->Create();
		}
	}
	return folder;
}
VError VFolder::CopyTo( const VFolder& inDestinationFolder, VFolder **outFolder, FileCopyOptions inOptions) const
{
	VError err = VE_OK;
	VFolder *folder = NULL;

	if (IsSameFolder( &inDestinationFolder) || inDestinationFolder.GetPath().IsChildOf( GetPath()))
	{
		StThrowFileError errThrow( this, VE_CANNOT_COPY_ON_ITSELF);
		errThrow->SetString( "destination", inDestinationFolder.GetPath().GetPath());
		err = errThrow.GetError();
	}
	else
	{
		VString name;
		GetName( name);

		folder = new VFolder( inDestinationFolder, name);
		if (folder != NULL)
		{
			if ( ( (inOptions & FCP_Overwrite) != 0) && folder->Exists() )
				err = folder->Delete( true);
			if (err == VE_OK)
				err = CopyContentsTo( *folder, inOptions);
		}
		else
		{
			err = VE_MEMORY_FULL;
		}
	}

	if (outFolder != NULL)
	{
		*outFolder = folder;
		folder = NULL;
	}

	ReleaseRefCountable( &folder);
		
	return err;
}
VError VFolder::CopyContentsTo( const VFolder& inDestinationFolder, FileCopyOptions inOptions) const
{
	VError err = VE_OK;
	if (!inDestinationFolder.Exists())
	{
		// this easy case should be handled by system implementation
		err = inDestinationFolder.Create();
	}
	else if (IsSameFolder( &inDestinationFolder) || inDestinationFolder.GetPath().IsChildOf( GetPath()))
	{
		StThrowFileError errThrow( this, VE_CANNOT_COPY_ON_ITSELF);
		errThrow->SetString( "destination", inDestinationFolder.GetPath().GetPath());
		err = errThrow.GetError();
	}

	if (err == VE_OK)
	{
		bool ok = true;
		
		for( VFolderIterator folderIterator( this, FI_WANT_FOLDERS | FI_WANT_INVISIBLES) ; folderIterator.IsValid() && ok ; ++folderIterator)
		{
			VError err2 = folderIterator->CopyTo( inDestinationFolder, NULL, inOptions);
			if (err == VE_OK)
				err = err2;
			ok = (err == VE_OK) | ((inOptions & FCP_ContinueOnError) != 0);
		}
		
		for( VFileIterator fileIterator( this, FI_WANT_FILES | FI_WANT_INVISIBLES) ; fileIterator.IsValid() && ok ; ++fileIterator)
		{
			VError err2 = fileIterator->CopyTo( inDestinationFolder, NULL, inOptions);
			if (err == VE_OK)
				err = err2;
			ok = (err == VE_OK) | ((inOptions & FCP_ContinueOnError) != 0);
		}
	}
	
	return err;
}
VFolder *VProcess::RetainProductSystemFolder( ESystemFolderKind inSelector, bool inCreateFolderIfNotFound) const
{
	VFolder *folder = NULL;
	
	bool allUsers;
	bool useProductSubFolder;
	ESystemFolderKind currentUserFolder;
	switch( inSelector)
	{
		case eFK_UserDocuments:
		case eFK_Temporary:
			allUsers = true;
			useProductSubFolder = true;
			break;

		case eFK_CommonPreferences:
			currentUserFolder = eFK_UserPreferences;
			allUsers = true;
			useProductSubFolder = true;
			break;

		case eFK_CommonApplicationData:
			currentUserFolder = eFK_UserApplicationData;
			allUsers = true;
			useProductSubFolder = true;
			break;

		case eFK_CommonCache:
			currentUserFolder = eFK_UserCache;
			allUsers = true;
			useProductSubFolder = true;
			break;

		case eFK_UserPreferences:
		case eFK_UserApplicationData:
		case eFK_UserCache:
			allUsers = false;
			useProductSubFolder = true;
			break;
		
		default:
			allUsers = false;
			useProductSubFolder = false;
			break;
	}
	
	if (useProductSubFolder)
	{
		VFolder *parent = VFolder::RetainSystemFolder( inSelector, inCreateFolderIfNotFound);
		if (parent != NULL)
		{
			VError err;
			VString folderName;
			GetProductName( folderName);

			// accepte un alias
			VString aliasName( folderName);
			#if VERSIONWIN
			aliasName += ".lnk";
			#endif
			VFile aliasFile( *parent, aliasName);
			if (aliasFile.Exists() && aliasFile.IsAliasFile())
			{
				VFilePath target;
				err = aliasFile.ResolveAlias( target);
				if ( (err == VE_OK) && target.IsFolder() )
				{
					folder = new VFolder( target);
				}
			}

			if (folder == NULL)
			{
				folder = new VFolder( *parent, folderName);
			}
			
			if (!folder->Exists())
			{
				if (inCreateFolderIfNotFound)
				{
					if (allUsers)
					{
						// drop errors if we can retry in current user home directory
						StErrorContextInstaller context( false);
						err = folder->CreateRecursive( allUsers);
					}
					else
					{
						err = folder->CreateRecursive( allUsers);
					}
					if (err != VE_OK)
					{
						ReleaseRefCountable( &folder);
						
						// si on nous a demande de creer dans "all users", on ressaie dans le dossier de l'utilisateur courant
						if (allUsers)
						{
							folder = RetainProductSystemFolder( currentUserFolder, inCreateFolderIfNotFound);
						}
					}
				}
				else
				{
					ReleaseRefCountable( &folder);
				}
			}
		}

		ReleaseRefCountable( &parent);
	}
	else
	{
		folder = VFolder::RetainSystemFolder( inSelector, inCreateFolderIfNotFound);
	}

	return folder;
}
VFolder* VProcess::RetainFolder( VProcess::EFolderKind inSelector) const
{
	VFolder* folder = NULL;
	
	switch (inSelector)
	{
		case eFS_Executable:
			folder = new VFolder( GetExecutableFolderPath());
			break;
		
		case eFS_Bundle:
			#if VERSIONWIN || VERSION_LINUX
			folder = new VFolder( GetExecutableFolderPath());
			#elif VERSIONMAC
			folder = new VFolder( GetExecutableFolderPath().ToParent().ToParent());
			#endif
			break;

		case eFS_Resources:
			{
				#if VERSIONWIN || VERSION_LINUX
				VFolder *parent = new VFolder( GetExecutableFolderPath());
				#elif VERSIONMAC
				VFolder *parent = new VFolder( GetExecutableFolderPath().ToParent());	// Contents
				#endif

				if (parent != NULL)
					folder = new VFolder( *parent, CVSTR( "Resources"));
				
				ReleaseRefCountable( &parent);
				break;
			}
		
		case eFS_InfoPlist:
			{
				// Resources folder on windows.
				// Contents folder on mac.
				#if VERSIONWIN || VERSION_LINUX
				folder = RetainFolder( eFS_Resources);
				#elif VERSIONMAC
				folder = new VFolder( GetExecutableFolderPath().ToParent());
				#endif
				break;
			}
		
		case eFS_NativeComponents:
			{
				#if VERSIONWIN || VERSION_LINUX
				folder = new VFolder( GetExecutableFolderPath().ToSubFolder( CVSTR( "Native Components")));
				#elif VERSIONMAC
				folder = new VFolder( GetExecutableFolderPath().ToParent().ToSubFolder( CVSTR( "Native Components")));
				#endif
				
				// in debug mode the "Native Components" might be next the bundle folder to be shared among mono, server, studio, server
				#if VERSIONDEBUG
				if ( (folder == NULL) || !folder->Exists() )
				{
					ReleaseRefCountable( &folder);
					#if VERSIONWIN || VERSION_LINUX
					folder = new VFolder( GetExecutableFolderPath().ToParent().ToSubFolder( CVSTR( "Native Components")));
					#elif VERSIONMAC
					folder = new VFolder( GetExecutableFolderPath().ToParent().ToParent().ToParent().ToSubFolder( CVSTR( "Native Components")));
					#endif
				}
				#endif
				
				break;
			}
		
		case eFS_DTDs:
			{
				VFolder *parent = RetainFolder( eFS_Resources);
				if (parent != NULL)
					folder = new VFolder( *parent, CVSTR( "DTD"));
				ReleaseRefCountable( &parent);
				break;
			}
		
		case eFS_XSDs:
			{
				VFolder *parent = RetainFolder( eFS_Resources);
				if (parent != NULL)
					folder = new VFolder( *parent, CVSTR( "XSD"));
				ReleaseRefCountable( &parent);
				break;
			}
		
		case eFS_XSLs:
			{
				VFolder *parent = RetainFolder( eFS_Resources);
				if (parent != NULL)
					folder = new VFolder( *parent, CVSTR( "XSL"));
				ReleaseRefCountable( &parent);
				break;
			}
		
		default:
			break;
	}

	return folder;
}
VError XWinFolder::RetainSystemFolder( ESystemFolderKind inFolderKind, bool inCreateFolder, VFolder **outFolder )
{
	VString folderPath;
	UniChar path[4096];
	size_t maxLength = sizeof( path)/sizeof( UniChar);
	path[maxLength-2]=0;
	VFolder* sysFolder = NULL;
	DWORD winErr = ERROR_PATH_NOT_FOUND;
	switch( inFolderKind)
	{
		case eFK_Executable:
			{
				DWORD pathLength = ::GetModuleFileNameW( NULL, path, (DWORD) maxLength);
				if (testAssert( pathLength != 0 && !path[maxLength-2])) 
				{
					folderPath.FromUniCString( path );
					VFile exeFile( folderPath );
					sysFolder = exeFile.RetainParentFolder();
					winErr = 0;
				}
				break;
			}

		case eFK_Temporary:
			{
				DWORD length = ::GetTempPathW( (DWORD) maxLength, path);
				if ( (length > 0) && (length <= maxLength) && !path[maxLength-2])
				{
					DWORD size = ::GetLongPathNameW( path, NULL, 0);
					if (size > 0)
					{
						UniChar *p = folderPath.GetCPointerForWrite( size-1);
						if (p != NULL)
						{
							DWORD result = ::GetLongPathNameW( path, p, size);
							if (result == 0)
								winErr = GetLastError();
							else
								winErr = 0;
							folderPath.Validate( result);
							sysFolder = new VFolder( folderPath );
						}
					}
				}
				break;
			}

		default:
			{
				int type;
				switch( inFolderKind)
				{
					case eFK_UserDocuments:			type = CSIDL_PERSONAL; break;
					case eFK_CommonPreferences:		type = CSIDL_COMMON_APPDATA; break;
					case eFK_UserPreferences:		type = CSIDL_APPDATA; break;
					case eFK_CommonApplicationData:	type = CSIDL_COMMON_APPDATA; break;
					case eFK_UserApplicationData:	type = CSIDL_APPDATA; break;
					case eFK_CommonCache:			type = CSIDL_COMMON_APPDATA; break;
					case eFK_UserCache:				type = CSIDL_LOCAL_APPDATA; break;
					default: xbox_assert( false);	type = CSIDL_APPDATA; break;
				}
				HRESULT result = ::SHGetFolderPathW( NULL, type, NULL, SHGFP_TYPE_CURRENT, path);
				if ( result == S_OK || result == S_FALSE )	// S_FALSE means The CSIDL is valid, but the folder does not exist.
				{
					folderPath.FromUniCString( path);
					if (folderPath[folderPath.GetLength()-1] != FOLDER_SEPARATOR)
						folderPath += FOLDER_SEPARATOR;
					sysFolder = new VFolder( folderPath );
					winErr = 0;
				}
				break;
			}
	}

	if ( (sysFolder != NULL) && !sysFolder->Exists() )
	{
		if (inCreateFolder)
		{
			if (sysFolder->CreateRecursive() != VE_OK)
				ReleaseRefCountable( &sysFolder);
		}
		else
		{
			ReleaseRefCountable( &sysFolder);
		}
	}

	*outFolder = sysFolder;
	return MAKE_NATIVE_VERROR( winErr);
}