VError VFolder::CreateRecursive(bool inMakeWritableByAll)
{
	VError err = VE_OK;
	if ( !fFolder.Exists( true) )
	{
		VFolder *parent = RetainParentFolder();
		if ( parent )
		{
			err = parent->CreateRecursive(inMakeWritableByAll);
			parent->Release();
			if ( err == VE_OK )
			{
				err = Create();
#if !VERSION_LINUX
				if ((err == VE_OK) && inMakeWritableByAll)
				{
					err = MakeWritableByAll();
				}
#endif
			}
		}
		else
		{
			err = Create();
#if !VERSION_LINUX
			if ((err == VE_OK) && inMakeWritableByAll)
			{
				err = MakeWritableByAll();
			}
#endif
		}
	}
	return err;
}
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;
}
VError VArchiveUnStream::ProceedFile()
{
	VError result = VE_OK;
	bool userAbort = false;
	uLONG8 partialByteCount = 0;

	if ( fCallBack )
		fCallBack(CB_OpenProgress,partialByteCount,fTotalByteCount,userAbort);

	VFileDesc *fileDesc = NULL;
	VSize bufferSize = 1024*1024;
	char *buffer = new char[bufferSize];
	for ( uLONG i = 0; i < fFileCatalog.size() && result == VE_OK; i++ )
	{
		fileDesc = NULL;
		if ( fStream->GetLong() == 'Fdat' )
		{
			if ( fFileCatalog[i]->GetExtractFlag() )
			{
				VFolder *parentFolder = fFileCatalog[i]->GetFile()->RetainParentFolder();
				if ( parentFolder )
				{
					result = parentFolder->CreateRecursive();
					parentFolder->Release();
				}
				if ( result == VE_OK )
				{
					result = fFileCatalog[i]->GetFile()->Open( FA_SHARED, &fileDesc, FO_CreateIfNotFound);
#if VERSIONMAC
					fFileCatalog[i]->GetFile()->MAC_SetKind(fFileCatalog[i]->GetKind());
					fFileCatalog[i]->GetFile()->MAC_SetCreator(fFileCatalog[i]->GetCreator());
#endif
				}
			}
			if ( result == VE_OK )
			{
				result = _ExtractFile( fFileCatalog[i], fileDesc, buffer, bufferSize, partialByteCount );
				delete fileDesc;
			}
			if ( result == VE_OK )
			{
				fileDesc = NULL;
				if ( fStream->GetLong() == 'Frez' )
				{
					if ( fFileCatalog[i]->GetExtractFlag() )
					{
						#if VERSIONMAC
						result = fFileCatalog[i]->GetFile()->Open( FA_SHARED, &fileDesc, FO_OpenResourceFork);
						#endif
					}
					if ( result == VE_OK )
					{
						result = _ExtractFile( fFileCatalog[i], fileDesc, buffer, bufferSize, partialByteCount );
						delete fileDesc;
					}
				}
				else
				{
					result = VE_STREAM_BAD_SIGNATURE;
				}
			}
		}
		else
		{
			result = VE_STREAM_BAD_SIGNATURE;
		}
	}
	delete[] buffer;

	if ( fCallBack )
		fCallBack(CB_CloseProgress,partialByteCount,fTotalByteCount,userAbort);

	return result;
}
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;
}
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);
}