Beispiel #1
0
// ---------------------------------------------------------------------------
// CScavenger::NukeDowloadedCache()
// scavenging interface
//---------------------------------------------------------------------------
HRESULT CScavenger::NukeDownloadedCache()
{
    HRESULT hr=S_OK;
    WCHAR szCachePath[MAX_PATH+1];
    DWORD dwLen=MAX_PATH;

    if(FAILED(hr = GetCachePath(ASM_CACHE_DOWNLOAD, szCachePath, &dwLen)))
        goto exit;

    // remove the complete downloaded dir. tree
    hr = RemoveDirectoryAndChildren(szCachePath);

    if( (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) )  
           || (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) )
    {
        hr = S_OK;
    }

    if(SUCCEEDED(hr))
    {
        SetDownLoadUsage( FALSE, 0);
    }

exit :
    return hr;
}
bool BackgroundLoader::IsCacheFileFinished( const CString &sFile, CString &sActualPath )
{
	if( !g_bEnableBackgroundLoading )
	{
		sActualPath = sFile;
		return true;
	}

	if( sFile == "" )
	{
		sActualPath = "";
		return true;
	}

	m_Mutex.Lock();

	map<CString,int>::iterator it;
	it = m_FinishedRequests.find( sFile );
	if( it == m_FinishedRequests.end() )
	{
		m_Mutex.Unlock();
		return false;
	}

	LOG->Trace("XXX: %s finished (%i)", sFile.c_str(), it->second);
	sActualPath = GetCachePath( sFile );

	m_Mutex.Unlock();
	return true;
}
Beispiel #3
0
static int
MirrorFlushFileBuffers( LPCWSTR	FileName,
                        PDOKAN_FILE_INFO DokanFileInfo )
{
	WCHAR        filePath[MAX_PATH+1];
    WCHAR        cachePath[MAX_PATH+1];
    CFS_HANDLE * lpcfs       = ((CFS_HANDLE*)DokanFileInfo->Context);
	HANDLE       fileHandle  = lpcfs->fileHandle;
    HANDLE       cacheHandle = lpcfs->cacheHandle;
	HANDLE       handle      = cacheHandle;

	GetFilePath(filePath, FileName);
    GetCachePath(cachePath, FileName);
    
	DbgPrint(L"FlushFileBuffers : %s\n", filePath);

	if (!handle || handle == INVALID_HANDLE_VALUE) {
		DbgPrint(L"\tinvalid handle\n\n");
		return 0;
	}

	if (FlushFileBuffers(handle)) {
		return 0;
	} else {
		DbgPrint(L"\tflush error code = %d\n", GetLastError());
		return -1;
	}

}
Beispiel #4
0
HRESULT UpdatePublisherPolicyTimeStampFile(IAssemblyName *pName)
{
    HRESULT                                 hr = S_OK;
    DWORD                                   dwSize;
    HANDLE                                  hFile = INVALID_HANDLE_VALUE;
    WCHAR                                   wzTimeStampFile[MAX_PATH + 1];
    WCHAR                                   wzAsmName[MAX_PATH];

    ASSERT(pName);

    // If the name of the assembly begins with "policy." then update
    // the publisher policy timestamp file.

    wzAsmName[0] = L'\0';

    dwSize = MAX_PATH;
    hr = pName->GetProperty(ASM_NAME_NAME, wzAsmName, &dwSize);
    if (FAILED(hr)) {
        goto Exit;
    }

    if (StrCmpNI(wzAsmName, POLICY_ASSEMBLY_PREFIX, lstrlenW(POLICY_ASSEMBLY_PREFIX))) {
        // No work needs to be done

        goto Exit;
    }

    // Touch the file

    dwSize = MAX_PATH;
    hr = GetCachePath(ASM_CACHE_GAC, wzTimeStampFile, &dwSize);
    if (lstrlenW(wzTimeStampFile) + lstrlenW(FILENAME_PUBLISHER_PCY_TIMESTAMP) + 1 >= MAX_PATH) {
        hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
        goto Exit;
    }
        
    PathRemoveBackslash(wzTimeStampFile);
    lstrcatW(wzTimeStampFile, FILENAME_PUBLISHER_PCY_TIMESTAMP);

    hFile = CreateFileW(wzTimeStampFile, GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE) {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

Exit:
    if (hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(hFile);
    }
    
    return hr;
} 
Beispiel #5
0
/// ディレクトリのハンドルを取得
static int MirrorOpenDirectory(
	LPCWSTR					FileName,
	PDOKAN_FILE_INFO		DokanFileInfo)
{
    CFS_HANDLE * lpcfs = ((CFS_HANDLE*)DokanFileInfo->Context);
	DWORD attr;

	//GetFilePath(filePath, FileName);

	//wprintf(L"OpenDirectory : %s\n", FileName);

    if ( ! lpcfs ) {
                
        lpcfs = new CFS_HANDLE;
        lpcfs->AccessMode = 0;
        lpcfs->ShareMode  = FILE_SHARE_WRITE|FILE_SHARE_READ;
        lpcfs->CreationDisposition = OPEN_EXISTING;
        lpcfs->FlagsAndAttributes  = FILE_FLAG_BACKUP_SEMANTICS;
        DokanFileInfo->Context = (ULONG64)lpcfs;
            
        if (wcslen(lpcfs->filePath)==0)
            GetFilePath(lpcfs->filePath, FileName);
        if (wcslen(lpcfs->cachePath)==0)
            GetCachePath(lpcfs->cachePath, FileName);
    }
    
	attr = GetFileAttributes(lpcfs->filePath);
	if (attr == INVALID_FILE_ATTRIBUTES) {
		DWORD error = GetLastError();
		//wprintf(L"\terror code = %d\n\n", error);
		return error * -1;
	}

	lpcfs->fileHandle = CreateFile(
		lpcfs->filePath,
		0,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_BACKUP_SEMANTICS,
		NULL);

	if (lpcfs->fileHandle == INVALID_HANDLE_VALUE) {
		DWORD error = GetLastError();
		//wprintf(L"\terror code = %d\n\n", error);
		return error * -1;
	}

	//DbgPrint(L"\n");

	return 0;
}
Beispiel #6
0
void CResourceManager::CleanCachedPage(nid aPageId)
{
    int len = GetCachePath().Length();
    HBufC* cache = HBufC::New(len + 64);
    TPtr p = cache->Des();
    TPtr path = GetCachePath();
    p.Format(KCachePathFormat, &path, aPageId);
    
    _LIT(KWildName, "*.*");
    RFs& fs = CCoeEnv::Static()->FsSession();
    TFindFile file_finder(fs);
    CDir* file_list;
    TInt err = file_finder.FindWildByDir(KWildName, p, file_list);
    while (err == KErrNone) {
        for (TInt i = 0; i < file_list->Count(); i++) {
            if ((*file_list)[i].IsDir())
                continue;

            TParse fullentry;
            fullentry.Set((*file_list)[i].iName, &file_finder.File(), NULL);
            if (fullentry.ExtPresent()) {
                err = fs.Delete(fullentry.FullName());
            }
            else {
                TFileName filename;
                filename.Append(fullentry.DriveAndPath());
                filename.Append(fullentry.Name());
                err = fs.Delete(filename);
            }
        }
        delete file_list;
        err = file_finder.FindWild(file_list);
    }

    err = fs.RmDir(p);
    delete cache;
}
BackgroundLoader::~BackgroundLoader()
{
	if( !g_bEnableBackgroundLoading )
		return;

	Abort();

	m_bShutdownThread = true;
	m_StartSem.Post();
	m_LoadThread.Wait();

	/* Delete all leftover cached files. */
	map<CString,int>::iterator it;
	for( it = m_FinishedRequests.begin(); it != m_FinishedRequests.end(); ++it )
		FILEMAN->Remove( GetCachePath( it->first ) );

	/* m_sCachePathPrefix should be filled with several empty directories.  Delete
	 * them and m_sCachePathPrefix, so we don't leak them. */
	DeleteEmptyDirectories( m_sCachePathPrefix );
}
void BackgroundLoader::FinishedWithCachedFile( const CString &sFile )
{
	if( !g_bEnableBackgroundLoading )
		return;

	if( sFile == "" )
		return;

	map<CString,int>::iterator it;
	it = m_FinishedRequests.find( sFile );
	ASSERT_M( it != m_FinishedRequests.end(), sFile );

	--it->second;
	ASSERT_M( it->second >= 0, ssprintf("%i", it->second) );
	if( !it->second )
	{
		m_FinishedRequests.erase( it );
		FILEMAN->Remove( GetCachePath( sFile ) );
	}
}
Beispiel #9
0
void CLocalHtmlFile::TranslateForOffline(DOM_NODE *node) {
	LOG1(5, "CLocalHtmlFile::TranslateForOffline(%p)", node);

	//
	const char *tag = domNodeGetName(node);
	if (tag != NULL && node != NULL) {
		if (_stricmp(tag, "img") == 0) {
//			LOG1(1, "img: %s", domElementGetAttribute(node, "src"));
			const char *src = domElementGetAttribute(node, "src");
			if (src != NULL) {
				CString value = CharToWChar(src);
				
				// CString url = MakeAbsoluteUrl(value, Server, ActivePath);
				CString url;
				url.Format(_T("%S"),MakeAbsoluteUrl(value, Server, ActivePath));
				if (IsHTMLCached(url, FALSE)) {
					CString fileName = UrlToFileName(url, FALSE);
					CString path = GetCachePath(FILE_TYPE_HTML, Config.CacheLocation);
					CString strFileName = MakeOfflineUrl(path, fileName);

					char *s = WCharToChar(strFileName);
					domElementSetAttribute(node, "src", s);
					delete [] s;
				}
				else
					domElementSetAttribute(node, "src", "");
			}
		}
	}

	DOM_NODE *child = domNodeGetFirstChild(node);
	while (child != NULL) {
		TranslateForOffline(child);
		child = domNodeGetNextSibling(child);
	}
}
void BackgroundLoader::LoadThread()
{
	while( !m_bShutdownThread )
	{
		/* Wait for a request.  It's normal for this to wait for a long time; don't
		 * fail on timeout. */
		m_StartSem.Wait();

		CString sFile = GetRequest();
		if( sFile.empty() )
			continue;

		{
			/* If the file already exists, short circuit. */
			m_Mutex.Lock();
			map<CString,int>::iterator it;
			it = m_FinishedRequests.find( sFile );
			if( it != m_FinishedRequests.end() )
			{
				++it->second;
				LOG->Trace("XXX: request %s done loading (already done), cnt now %i", sFile.c_str(), m_FinishedRequests[sFile] );
				m_Mutex.Unlock();
				continue;
			}
			m_Mutex.Unlock();
		}

		m_sThreadIsActive = true;

		LOG->Trace("XXX: reading %s", sFile.c_str());

		CString sCachePath = GetCachePath( sFile );

		/* Open the file and read it. */
		RageFile src;
		if( src.Open(sFile) )
		{
			/* If we're writing to a file cache ... */
			RageFile dst;

			bool bWriteToCache = g_bWriteToCache;
			if( bWriteToCache )
				bWriteToCache = dst.Open( sCachePath, RageFile::WRITE );
			LOG->Trace("XXX: go on '%s' to '%s'", sFile.c_str(), sCachePath.c_str());
			
			char buf[1024*4];
			while( !m_sThreadShouldAbort && !src.AtEOF() )
			{
				int got = src.Read( buf, sizeof(buf) );
				if( got > 0 && bWriteToCache )
					dst.Write( buf, got );
			}
			if( bWriteToCache )
				dst.Close();

			LOG->Trace("XXX: done");
		}
		src.Close();

		m_Mutex.Lock();
		if( !m_sThreadShouldAbort )
		{
			++m_FinishedRequests[sFile];
			LOG->Trace("XXX: request %s done loading, cnt now %i", sFile.c_str(), m_FinishedRequests[sFile] );
		}
		else
		{
			FILEMAN->Remove( sCachePath );

			LOG->Trace("XXX: request %s aborted", sFile.c_str() );
		}

		m_sThreadShouldAbort = false;
		m_sThreadIsActive = false;
		m_Mutex.Unlock();
	}
}
Beispiel #11
0
void Emulator::Load(bool add_only)
{
	Stop();

	try
	{
		Init();

		// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations) 
		YAML::Node games = YAML::Load(fs::file{fs::get_config_dir() + "/games.yml", fs::read + fs::create}.to_string());

		if (!games.IsMap())
		{
			games.reset();
		}

		LOG_NOTICE(LOADER, "Path: %s", m_path);

		const std::string elf_dir = fs::get_parent_dir(m_path);

		// Load PARAM.SFO (TODO)
		const auto _psf = psf::load_object([&]
		{
			if (fs::file sfov{elf_dir + "/sce_sys/param.sfo"})
			{
				return sfov;
			}
			else
			{
				return fs::file(elf_dir + "/../PARAM.SFO");
			}
		}());
		m_title = psf::get_string(_psf, "TITLE", m_path);
		m_title_id = psf::get_string(_psf, "TITLE_ID");
		const auto _cat = psf::get_string(_psf, "CATEGORY");

		LOG_NOTICE(LOADER, "Title: %s", GetTitle());
		LOG_NOTICE(LOADER, "Serial: %s", GetTitleID());

		// Initialize data/cache directory
		m_cache_path = fs::get_data_dir(m_title_id, m_path);
		LOG_NOTICE(LOADER, "Cache: %s", GetCachePath());

		// Load custom config-0
		if (fs::file cfg_file{m_cache_path + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s/config.yml", m_cache_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-1
		if (fs::file cfg_file{fs::get_config_dir() + "data/" + m_title_id + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: data/%s/config.yml", m_title_id);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-2
		if (fs::file cfg_file{m_path + ".yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s.yml", m_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string());

		// Load patches from different locations
		fxm::check_unlocked<patch_engine>()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml");
		fxm::check_unlocked<patch_engine>()->append(m_cache_path + "/patch.yml");

		// Mount all devices
		const std::string emu_dir_ = g_cfg.vfs.emulator_dir;
		const std::string emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
		const std::string home_dir = g_cfg.vfs.app_home;
		std::string bdvd_dir = g_cfg.vfs.dev_bdvd;

		vfs::mount("dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_hdd1", fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_flash", fmt::replace_all(g_cfg.vfs.dev_flash, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir));

		// Detect boot location
		const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
		const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");

		if (_cat == "DG" && m_path.find(hdd0_game + m_title_id + '/') != -1)
		{
			// Booting disc game from wrong location
			LOG_ERROR(LOADER, "Disc game found at invalid location: /dev_hdd0/game/%s/", m_title_id);

			// Move and retry from correct location
			if (fs::rename(hdd0_game + m_title_id, hdd0_disc + m_title_id))
			{
				LOG_SUCCESS(LOADER, "Disc game moved to special location: /dev_hdd0/disc/%s/", m_title_id);
				return SetPath(hdd0_disc + m_path.substr(hdd0_game.size())), Load();
			}
			else
			{
				LOG_ERROR(LOADER, "Failed to move disc game to /dev_hdd0/disc/%s/ (%s)", m_title_id, fs::g_tls_error);
				return;
			}
		}

		// Booting disc game
		if (_cat == "DG" && bdvd_dir.empty())
		{
			// Mount /dev_bdvd/ if necessary
			if (auto pos = elf_dir.rfind("/PS3_GAME") + 1)
			{
				bdvd_dir = elf_dir.substr(0, pos);
			}
		}

		// Booting patch data
		if (_cat == "GD" && bdvd_dir.empty())
		{
			// Load /dev_bdvd/ from game list if available
			if (auto node = games[m_title_id])
			{
				bdvd_dir = node.Scalar();
			}
			else
			{
				LOG_FATAL(LOADER, "Disc directory not found. Try to run the game from the actual game disc directory.");
			}
		}

		// Check /dev_bdvd/
		if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
		{
			fs::file sfb_file;

			vfs::mount("dev_bdvd", bdvd_dir);
			LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd"));

			if (!sfb_file.open(vfs::get("/dev_bdvd/PS3_DISC.SFB")) || sfb_file.size() < 4 || sfb_file.read<u32>() != ".SFB"_u32)
			{
				LOG_ERROR(LOADER, "Invalid disc directory for the disc game %s", m_title_id);
				return;
			}

			const std::string bdvd_title_id = psf::get_string(psf::load_object(fs::file{vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")}), "TITLE_ID");

			if (bdvd_title_id != m_title_id)
			{
				LOG_ERROR(LOADER, "Unexpected disc directory for the disc game %s (found %s)", m_title_id, bdvd_title_id);
				return;
			}

			// Store /dev_bdvd/ location
			games[m_title_id] = bdvd_dir;
			YAML::Emitter out;
			out << games;
			fs::file(fs::get_config_dir() + "/games.yml", fs::rewrite).write(out.c_str(), out.size());
		}
		else if (_cat == "DG" || _cat == "GD")
		{
			LOG_ERROR(LOADER, "Failed to mount disc directory for the disc game %s", m_title_id);
			return;
		}

		if (add_only)
		{
			LOG_NOTICE(LOADER, "Finished to add data to games.yml by boot for: %s", m_path);
			return;
		}

		// Check game updates
		const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN";

		if (_cat == "DG" && fs::is_file(hdd0_boot))
		{
			// Booting game update
			LOG_SUCCESS(LOADER, "Updates found at /dev_hdd0/game/%s/!", m_title_id);
			return SetPath(hdd0_boot), Load();
		}

		// Mount /host_root/ if necessary
		if (g_cfg.vfs.host_root)
		{
			vfs::mount("host_root", {});
		}

		// Open SELF or ELF
		fs::file elf_file(m_path);

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to open executable: %s", m_path);
			return;
		}

		// Check SELF header
		if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32)
		{
			const std::string decrypted_path = m_cache_path + "boot.elf";

			fs::stat_t encrypted_stat = elf_file.stat();
			fs::stat_t decrypted_stat;

			// Check modification time and try to load decrypted ELF
			if (fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime)
			{
				elf_file.open(decrypted_path);
			}
			else
			{
				// Decrypt SELF
				elf_file = decrypt_self(std::move(elf_file));

				if (fs::file elf_out{decrypted_path, fs::rewrite})
				{
					elf_out.write(elf_file.to_vector<u8>());
					elf_out.close();
					fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime);
				}
				else
				{
					LOG_ERROR(LOADER, "Failed to create boot.elf");
				}
			}
		}

		ppu_exec_object ppu_exec;
		ppu_prx_object ppu_prx;
		spu_exec_object spu_exec;
		arm_exec_object arm_exec;

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to decrypt SELF: %s", m_path);
			return;
		}
		else if (ppu_exec.open(elf_file) == elf_error::ok)
		{
			// PS3 executable
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();

			vm::ps3::init();

			if (m_elf_path.empty())
			{
				if (m_path.find(hdd0_game) != -1)
				{
					m_elf_path = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size());
				}
				else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
				{
					//Disc games are on /dev_bdvd/
					size_t pos = m_path.rfind("PS3_GAME");
					m_elf_path = "/dev_bdvd/" + m_path.substr(pos);
				}
				else
				{
					//For homebrew
					m_elf_path = "/host_root/" + m_path;
				}

				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			ppu_load_exec(ppu_exec);

			fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
		}
		else if (ppu_prx.open(elf_file) == elf_error::ok)
		{
			// PPU PRX (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			ppu_load_prx(ppu_prx, m_path);
		}
		else if (spu_exec.open(elf_file) == elf_error::ok)
		{
			// SPU executable (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			spu_load_exec(spu_exec);
		}
		else if (arm_exec.open(elf_file) == elf_error::ok)
		{
			// ARMv7 executable
			g_system = system_type::psv;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::psv::init();

			if (m_elf_path.empty())
			{
				m_elf_path = "host_root:" + m_path;
				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			arm_load_exec(arm_exec);
		}
		else
		{
			LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);

			LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error());
			LOG_WARNING(LOADER, "** ppu_prx  -> %s", ppu_prx.get_error());
			LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error());
			LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error());
			return;
		}

		if (g_cfg.misc.autostart && IsReady())
		{
			Run();
		}
		else if (IsPaused())
		{
			m_state = system_state::ready;
			GetCallbacks().on_ready();
		}
	}
	catch (const std::exception& e)
	{
		LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what());
		Stop();
	}
}
Beispiel #12
0
void Emulator::Load()
{
	Stop();

	try
	{
		Init();

		// Open SELF or ELF
		fs::file elf_file(m_path);

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to open file: %s", m_path);
			return;
		}

		LOG_NOTICE(LOADER, "Path: %s", m_path);

		const std::string elf_dir = fs::get_parent_dir(m_path);
		const fs::file sfov(elf_dir + "/sce_sys/param.sfo");
		const fs::file sfo1(elf_dir + "/../PARAM.SFO");

		// Load PARAM.SFO (TODO)
		const auto _psf = psf::load_object(sfov ? sfov : sfo1);
		m_title = psf::get_string(_psf, "TITLE", m_path);
		m_title_id = psf::get_string(_psf, "TITLE_ID");

		LOG_NOTICE(LOADER, "Title: %s", GetTitle());
		LOG_NOTICE(LOADER, "Serial: %s", GetTitleID());

		// Initialize data/cache directory
		m_cache_path = fs::get_data_dir(m_title_id, m_path);
		LOG_NOTICE(LOADER, "Cache: %s", GetCachePath());

		// Load custom config-0
		if (fs::file cfg_file{m_cache_path + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s/config.yml", m_cache_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-1
		if (fs::file cfg_file{fs::get_config_dir() + "data/" + m_title_id + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: data/%s/config.yml", m_title_id);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-2
		if (fs::file cfg_file{m_path + ".yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s.yml", m_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string());

		// Load patches from different locations
		fxm::check_unlocked<patch_engine>()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml");
		fxm::check_unlocked<patch_engine>()->append(m_cache_path + "/patch.yml");

		// Mount all devices
		const std::string emu_dir_ = g_cfg.vfs.emulator_dir;
		const std::string emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
		const std::string home_dir = g_cfg.vfs.app_home;
		std::string bdvd_dir = g_cfg.vfs.dev_bdvd;

		vfs::mount("dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_hdd1", fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_flash", fmt::replace_all(g_cfg.vfs.dev_flash, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir));

		// Mount /dev_bdvd/ if necessary
		if (bdvd_dir.empty()) 
		{
			size_t pos = elf_dir.rfind("PS3_GAME");
			std::string temp = elf_dir.substr(0, pos);
			if ((pos != std::string::npos) && fs::is_file(temp + "/PS3_DISC.SFB")) {
				bdvd_dir = temp;
			}
		}
		if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
		{
			vfs::mount("dev_bdvd", fmt::replace_all(bdvd_dir, "$(EmulatorDir)", emu_dir));
			LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd"));
		}

		// Mount /host_root/ if necessary
		if (g_cfg.vfs.host_root)
		{
			vfs::mount("host_root", {});
		}

		// Check SELF header
		if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32)
		{
			const std::string decrypted_path = m_cache_path + "boot.elf";

			fs::stat_t encrypted_stat = elf_file.stat();
			fs::stat_t decrypted_stat;

			// Check modification time and try to load decrypted ELF
			if (fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime)
			{
				elf_file.open(decrypted_path);
			}
			else
			{
				// Decrypt SELF
				elf_file = decrypt_self(std::move(elf_file));

				if (fs::file elf_out{decrypted_path, fs::rewrite})
				{
					elf_out.write(elf_file.to_vector<u8>());
					elf_out.close();
					fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime);
				}
				else
				{
					LOG_ERROR(LOADER, "Failed to create boot.elf");
				}
			}
		}

		ppu_exec_object ppu_exec;
		ppu_prx_object ppu_prx;
		spu_exec_object spu_exec;
		arm_exec_object arm_exec;

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to decrypt SELF: %s", m_path);
			return;
		}
		else if (ppu_exec.open(elf_file) == elf_error::ok)
		{
			// PS3 executable
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();

			vm::ps3::init();

			if (m_elf_path.empty())
			{
				if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
				{
					//Disc games are on /dev_bdvd/
					size_t pos = m_path.rfind("PS3_GAME");
					m_elf_path = "/dev_bdvd/" + m_path.substr(pos);
				}
				else if (m_path.find(vfs::get("/dev_hdd0/game/")) != -1)
				{
					m_elf_path = "/dev_hdd0/game/" + m_path.substr(vfs::get("/dev_hdd0/game/").size());
				}
				else
				{
					//For homebrew
					m_elf_path = "/host_root/" + m_path;
				}

				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			ppu_load_exec(ppu_exec);

			fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
		}
		else if (ppu_prx.open(elf_file) == elf_error::ok)
		{
			// PPU PRX (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			ppu_load_prx(ppu_prx, "");
		}
		else if (spu_exec.open(elf_file) == elf_error::ok)
		{
			// SPU executable (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			spu_load_exec(spu_exec);
		}
		else if (arm_exec.open(elf_file) == elf_error::ok)
		{
			// ARMv7 executable
			g_system = system_type::psv;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::psv::init();

			if (m_elf_path.empty())
			{
				m_elf_path = "host_root:" + m_path;
				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			arm_load_exec(arm_exec);
		}
		else
		{
			LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);

			LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error());
			LOG_WARNING(LOADER, "** ppu_prx  -> %s", ppu_prx.get_error());
			LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error());
			LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error());
			return;
		}

		if (g_cfg.misc.autostart && IsReady())
		{
			Run();
		}
		else if (IsPaused())
		{
			m_state = system_state::ready;
			GetCallbacks().on_ready();
		}
	}
	catch (const std::exception& e)
	{
		LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what());
		Stop();
	}
}
Beispiel #13
0
static int
MirrorWriteFile(
	LPCWSTR		FileName,
	LPCVOID		Buffer,
	DWORD		NumberOfBytesToWrite,
	LPDWORD		NumberOfBytesWritten,
	LONGLONG			Offset,
	PDOKAN_FILE_INFO	DokanFileInfo)
{
    CFS_HANDLE * lpcfs  = ((CFS_HANDLE*)DokanFileInfo->Context);
	ULONG        offset      = (ULONG)Offset;
    bool         deleteContext = false;
    bool         closeHandle   = false;

    if ( ! lpcfs ) {

        deleteContext = true;

        lpcfs = new CFS_HANDLE;
        lpcfs->AccessMode = GENERIC_WRITE|GENERIC_READ|WRITE_OWNER;
        lpcfs->ShareMode  = FILE_SHARE_READ|FILE_SHARE_WRITE;
        lpcfs->CreationDisposition = OPEN_EXISTING;
        lpcfs->FlagsAndAttributes  = FILE_ATTRIBUTE_NORMAL;
        DokanFileInfo->Context = (ULONG64)lpcfs;
            
        if (wcslen(lpcfs->filePath)==0)
            GetFilePath(lpcfs->filePath, FileName);
        if (wcslen(lpcfs->cachePath)==0)
            GetCachePath(lpcfs->cachePath, FileName);

         // オリジナルのファイルのハンドルを取得
        lpcfs->fileHandle = CreateFile(
            lpcfs->filePath,
            lpcfs->AccessMode,
            lpcfs->ShareMode,
            NULL,
            lpcfs->CreationDisposition,
            lpcfs->FlagsAndAttributes,
            NULL);
        
        if (lpcfs->fileHandle == INVALID_HANDLE_VALUE) {
            DWORD error = GetLastError();
            DbgPrint(L"\terror code = %d\n\n", error);
            return error * -1;
        }
        
    }
    if ( lpcfs->fileHandle!=INVALID_HANDLE_VALUE &&
         ( ! lpcfs->cacheHandle || lpcfs->cacheHandle == INVALID_HANDLE_VALUE ) ) {
        
        // 必要であればキャッシュファイルを作成する
        if (needCopyFile(lpcfs->filePath, lpcfs->cachePath)) {
            copyFile(lpcfs->filePath, lpcfs->cachePath);
        }
        
        // CreateFileではキャッシュしない
        DWORD AccessMode = lpcfs->AccessMode;
        if ( lpcfs->AccessMode & GENERIC_EXECUTE ) AccessMode = GENERIC_READ;
       
        // キャッシュファイルのハンドルを取得
        lpcfs->cacheHandle = CreateFile(
            lpcfs->cachePath,
            lpcfs->AccessMode,
            lpcfs->ShareMode,
            NULL,
            lpcfs->CreationDisposition,
            lpcfs->FlagsAndAttributes,
            NULL);
        closeHandle = true;
    }

    // テストはキャッシュファイルに対して書き込む
	//HANDLE	handle = lpcfs->cacheHandle; // 何故かパラメータが違うってエラーになる(おそらくHANDLEの開き方?
	HANDLE	handle = lpcfs->fileHandle;

    DbgPrintAccessMode(lpcfs->AccessMode);
    DbgPrintShareMode(lpcfs->ShareMode);
    
	if (DokanFileInfo->WriteToEndOfFile) {
		if (SetFilePointer(handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) {
			DbgPrint(L"\tseek error, offset = EOF, error = %d\n", GetLastError());
			return -1;
		}
	} else if (SetFilePointer(handle, offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
		DbgPrint(L"\tseek error, offset = %d, error = %d\n", offset, GetLastError());
		return -1;
	}

		
	if (!WriteFile(handle, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, NULL)) {
		DbgPrint(L"\twrite error = %u, buffer length = %d, write length = %d\n",
			GetLastError(), NumberOfBytesToWrite, *NumberOfBytesWritten);
		return -1;

	} else {
		DbgPrint(L"\twrite %d, offset %d\n\n", *NumberOfBytesWritten, offset);
	}

    // 後処理
    //if ( closeHandle ) { CloseHandle(lpcfs->cacheHandle); lpcfs->cacheHandle = NULL; }
    if ( deleteContext ) {
        delete (CFS_HANDLE*)DokanFileInfo->Context;
        DokanFileInfo->Context = NULL;
    }

	return 0;
}
Beispiel #14
0
static int CFSOpenFileHandle(LPCWSTR     FileName,
                             DWORD       AccessMode,
                             DWORD       ShareMode,
                             DWORD       CreationDisposition,
                             DWORD       FlagsAndAttributes,
                             bool        execCache,
                             PDOKAN_FILE_INFO DokanFileInfo)
{
    DWORD error=0;
    CFS_HANDLE * lpcfs = ((CFS_HANDLE*)DokanFileInfo->Context);

    if (lpcfs==NULL) {
        lpcfs = new CFS_HANDLE;
        DokanFileInfo->Context = (ULONG64)lpcfs;
    }
    
    if (lpcfs->fileHandle==0 || lpcfs->fileHandle==INVALID_HANDLE_VALUE)
    {

        if (wcslen(lpcfs->filePath)==0)
            GetFilePath(lpcfs->filePath, FileName);

        // ディレクトリならばOpenDirectoryへ引き継ぐ
        DWORD attr = GetFileAttributes(lpcfs->filePath);
        if (attr!=-1 && attr & FILE_ATTRIBUTE_DIRECTORY) {
            FlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
            return MirrorOpenDirectory(FileName, DokanFileInfo);
        }

        lpcfs->AccessMode          = AccessMode;
        lpcfs->ShareMode           = ShareMode;
        lpcfs->CreationDisposition = CreationDisposition;
        lpcfs->FlagsAndAttributes  = FlagsAndAttributes;
                
        if (lpcfs->AccessMode & GENERIC_EXECUTE ||
            lpcfs->AccessMode & FILE_EXECUTE /*||
            lpcfs->AccessMode & STANDARD_RIGHTS_EXECUTE*/ ) {
            
            //DbgPrintAccessMode(lpcfs->AccessMode);

            lpcfs->AccessMode = GENERIC_READ|GENERIC_WRITE;
            lpcfs->ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
        }

        //wprintf(L"CreateFile: %s\n", lpcfs->filePath);
        //DbgPrintAccessMode(lpcfs->AccessMode);
        //DbgPrintShareMode(lpcfs->ShareMode);

        // オリジナルのファイルのハンドルを取得
        lpcfs->fileHandle = CreateFile(
            lpcfs->filePath,
            lpcfs->AccessMode,
            lpcfs->ShareMode|FILE_SHARE_READ|FILE_SHARE_WRITE,
            NULL,                       // security attribute
            lpcfs->CreationDisposition,
            lpcfs->FlagsAndAttributes,  // |FILE_FLAG_NO_BUFFERING,
            NULL);
    }
    
    if (lpcfs->fileHandle == INVALID_HANDLE_VALUE) {
        error = GetLastError();
        DbgPrint(L"\terror code = %d\n\n", error);
        //wprintf(L"ERROR: %d %s\n", error, lpcfs->filePath);
        return -1 * error;
    }

    if ( lpcfs->fileHandle!=INVALID_HANDLE_VALUE &&
         ( ! lpcfs->cacheHandle || lpcfs->cacheHandle == INVALID_HANDLE_VALUE ) ) {

        if (wcslen(lpcfs->cachePath)==0)
            GetCachePath(lpcfs->cachePath, FileName);

        if (execCache && needCopyFile(lpcfs->filePath, lpcfs->cachePath)) {
            copyFile(lpcfs->filePath, lpcfs->cachePath);
        }
        
        // 実行権があればGENERIC_READ
        //if ( lpcfs->AccessMode & GENERIC_EXECUTE )
        //    AccessMode = GENERIC_READ;
        //else
        //    AccessMode = lpcfs->AccessMode;

        // キャッシュファイルのハンドルを取得
        lpcfs->cacheHandle = CreateFile(
            lpcfs->cachePath,
            //AccessMode,
            lpcfs->AccessMode,
            //FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
            lpcfs->ShareMode,
            NULL,
            OPEN_EXISTING,
            lpcfs->FlagsAndAttributes,
            NULL);
    }

    return 0;
}