// --------------------------------------------------------------------------- // 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; }
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; } }
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; }
/// ディレクトリのハンドルを取得 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; }
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 ) ); } }
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(); } }
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(); } }
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(); } }
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; }
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; }