Error ValidateDestroyImageKHR(const Display *display, const Image *image) { ANGLE_TRY(ValidateImage(display, image)); if (!display->getExtensions().imageBase && !display->getExtensions().image) { // It is out of spec what happens when calling an extension function when the extension is // not available. // EGL_BAD_DISPLAY seems like a reasonable error. return Error(EGL_BAD_DISPLAY); } return Error(EGL_SUCCESS); }
HiresTexture* HiresTexture::Load(const std::string& basename, std::function<u8*(size_t)> request_buffer_delegate, bool cacheresult) { if (s_textureMap.size() == 0) { return nullptr; } HiresTextureCache::iterator iter = s_textureMap.find(basename); if (iter == s_textureMap.end()) { return nullptr; } HiresTextureCacheItem& current = iter->second; if (current.maps[MapType::color].size() == 0) { return nullptr; } // First level is mandatory if (current.maps[MapType::color][0].path.size() == 0) { return nullptr; } HiresTexture* ret = nullptr; u8* buffer_pointer; u32 maxwidth = 0; u32 maxheight = 0; bool last_level_is_dds = false; bool allocated_data = false; bool mipmapsize_included = false; size_t material_mat_index = current.maps[MapType::color].size() == current.maps[MapType::normal].size() && current.maps[MapType::normal].size() != current.maps[MapType::material].size() ? MapType::normal : MapType::material; size_t emissive_index = MapType::emissive; bool nrm_posible = current.maps[MapType::color].size() == current.maps[material_mat_index].size() && g_ActiveConfig.HiresMaterialMapsEnabled(); bool emissive_posible = current.maps[MapType::color].size() == current.maps[emissive_index].size() && g_ActiveConfig.HiresMaterialMapsEnabled(); size_t remaining_buffer_size = 0; size_t total_buffer_size = 0; std::function<u8*(size_t, bool)> first_level_function = [&](size_t requiredsize, bool mipmapsincluded) { // Allocate double side buffer if we are going to load normal maps allocated_data = true; mipmapsize_included = mipmapsincluded; // Pre allocate space for the textures and potetially all the posible mip levels if (current.maps[MapType::color].size() > 1 && !mipmapsincluded) { requiredsize = (requiredsize * 4) / 3; } requiredsize *= (nrm_posible && emissive_posible ? 3 : (nrm_posible || emissive_posible ? 2 : 1)); total_buffer_size = requiredsize; remaining_buffer_size = total_buffer_size; return request_buffer_delegate(requiredsize); }; std::function<u8*(size_t, bool)> allocation_function = [&](size_t requiredsize, bool mipmapsincluded) { // is required size is biguer that the remaining size on the packed buffer just reject if (requiredsize > remaining_buffer_size) { return static_cast<u8*>(nullptr); } // just return the pointer to pack the textures in a single buffer. return buffer_pointer; }; for (size_t level = 0; level < current.maps[MapType::color].size(); level++) { const hires_mip_level& item = current.maps[MapType::color][level]; ImageLoaderParams imgInfo = LoadMipLevel(item, level == 0 ? first_level_function : allocation_function, cacheresult); imgInfo.releaseresourcesonerror = cacheresult; nrm_posible = nrm_posible && current.maps[material_mat_index][level].path.size() > 0; emissive_posible = emissive_posible && current.maps[emissive_index][level].path.size() > 0; bool ddsfile = item.is_compressed && TexDecoder::IsCompressed(imgInfo.resultTex); if ((level > 0 && ddsfile != last_level_is_dds) || imgInfo.dst == nullptr || imgInfo.resultTex == PC_TEX_FMT_NONE) { // don't give support to mixed formats if (allocated_data && cacheresult && imgInfo.dst != nullptr) { delete[] imgInfo.dst; } break; } last_level_is_dds = ddsfile; if (level == 0) { ret = new HiresTexture(); ret->has_arbitrary_mips = current.has_arbitrary_mips; ret->m_format = imgInfo.resultTex; ret->m_width = maxwidth = imgInfo.Width; ret->m_height = maxheight = imgInfo.Height; if (cacheresult) { ret->m_cached_data.reset(imgInfo.dst); ret->m_cached_data_size = total_buffer_size; } } else { if (!ValidateImage(imgInfo, level, maxwidth, maxheight, ret->m_format, "color")) break; } ret->m_levels++; if (ddsfile) { u32 requiredsize = TextureUtil::GetTextureSizeInBytes(maxwidth, maxheight, imgInfo.resultTex); buffer_pointer = imgInfo.dst + requiredsize; remaining_buffer_size -= requiredsize; } else { buffer_pointer = imgInfo.dst + imgInfo.data_size; remaining_buffer_size -= imgInfo.data_size; } if (imgInfo.nummipmaps > 0) { // Give priority to load dds with packed levels ret->m_levels = imgInfo.nummipmaps + 1; if (nrm_posible || emissive_posible) { SkipMipData(ret->m_levels, imgInfo.Width, imgInfo.Height, ret->m_format, buffer_pointer, remaining_buffer_size); } break; } // no more mipmaps available if (maxwidth == 1 && maxheight == 1) break; maxwidth = std::max(maxwidth >> 1, 1u); maxheight = std::max(maxheight >> 1, 1u); } if (nrm_posible) { for (size_t level = 0; level < current.maps[material_mat_index].size(); level++) { const hires_mip_level& item = current.maps[material_mat_index][level]; ImageLoaderParams imgInfo = LoadMipLevel(item, allocation_function, cacheresult); bool ddsfile = item.is_compressed && TexDecoder::IsCompressed(imgInfo.resultTex); if ((level > 0 && ddsfile != last_level_is_dds) || imgInfo.dst == nullptr || imgInfo.resultTex == PC_TEX_FMT_NONE) { // don't give support to mixed formats break; } if (g_ActiveConfig.bHiresMaterialMapsBuild && imgInfo.resultTex == PC_TEX_FMT_RGBA32) { BuildMaterial(current, imgInfo, level); } if (level == 0) { maxwidth = imgInfo.Width; maxheight = imgInfo.Height; if (!ValidateImage(imgInfo, level, ret->m_width, ret->m_height, ret->m_format, "normal")) break; } else { if (!ValidateImage(imgInfo, level, maxwidth, maxheight, ret->m_format, "normal")) break; } ret->m_nrm_levels++; if (ddsfile) { u32 requiredsize = TextureUtil::GetTextureSizeInBytes(maxwidth, maxheight, imgInfo.resultTex); buffer_pointer = imgInfo.dst + requiredsize; remaining_buffer_size -= requiredsize; } else { buffer_pointer = imgInfo.dst + imgInfo.data_size; remaining_buffer_size -= imgInfo.data_size; } if (imgInfo.nummipmaps > 0) { // Give priority to load dds with packed levels ret->m_nrm_levels = imgInfo.nummipmaps + 1; if (emissive_posible) { SkipMipData(ret->m_nrm_levels, imgInfo.Width, imgInfo.Height, ret->m_format, buffer_pointer, remaining_buffer_size); } break; } // no more mipmaps available if (maxwidth == 1 && maxheight == 1) break; maxwidth = std::max(maxwidth >> 1, 1u); maxheight = std::max(maxheight >> 1, 1u); } } if (emissive_posible) { for (size_t level = 0; level < current.maps[emissive_index].size(); level++) { const hires_mip_level& item = current.maps[emissive_index][level]; ImageLoaderParams imgInfo = LoadMipLevel(item, allocation_function, cacheresult); bool ddsfile = item.is_compressed && TexDecoder::IsCompressed(imgInfo.resultTex); if ((level > 0 && ddsfile != last_level_is_dds) || imgInfo.dst == nullptr || imgInfo.resultTex == PC_TEX_FMT_NONE) { // don't give support to mixed formats break; } if (level == 0) { maxwidth = imgInfo.Width; maxheight = imgInfo.Height; if (!ValidateImage(imgInfo, level, ret->m_width, ret->m_height, ret->m_format, "normal")) break; } else { if (!ValidateImage(imgInfo, level, maxwidth, maxheight, ret->m_format, "normal")) break; } ret->m_lum_levels++; if (ddsfile) { u32 requiredsize = TextureUtil::GetTextureSizeInBytes(maxwidth, maxheight, imgInfo.resultTex); buffer_pointer = imgInfo.dst + requiredsize; remaining_buffer_size -= requiredsize; } else { buffer_pointer = imgInfo.dst + imgInfo.data_size; remaining_buffer_size -= imgInfo.data_size; } if (imgInfo.nummipmaps > 0) { // Give priority to load dds with packed levels ret->m_lum_levels = imgInfo.nummipmaps + 1; break; } // no more mipmaps available if (maxwidth == 1 && maxheight == 1) break; maxwidth = std::max(maxwidth >> 1, 1u); maxheight = std::max(maxheight >> 1, 1u); } } if (ret != nullptr) { u32 levels = ret->m_levels; // Disable normal map if the size or levels are different if (ret->m_nrm_levels != levels) { ret->m_nrm_levels = 0; } if (ret->m_lum_levels != levels) { ret->m_lum_levels = 0; } } return ret; }
/// <summary> /// Injection routine /// </summary> /// <param name="path">Image path</param> /// <param name="init">Initizliation routine/param> /// <param name="arg">Initizliation routine argument</param> /// <returns>Error code</returns> DWORD MainDlg::InjectWorker( std::wstring path, std::string init, std::wstring arg ) { blackbone::Thread *pThread = nullptr; const blackbone::ModuleData* mod = nullptr; PROCESS_INFORMATION pi = { 0 }; wchar_t cmdline[256] = { 0 }; HWND hCombo = GetDlgItem( _hMainDlg, IDC_THREADS ); DWORD thdId = (DWORD)ComboBox_GetItemData( hCombo, ComboBox_GetCurSel( hCombo ) ); bool bManual = ComboBox_GetCurSel( GetDlgItem( _hMainDlg, IDC_OP_TYPE ) ) == 1; GetDlgItemTextW( _hMainDlg, IDC_CMDLINE, cmdline, ARRAYSIZE( cmdline ) ); // Check export if (ValidateInit( init.c_str() ) != STATUS_SUCCESS) return ERROR_CANCELLED; // Create new process if (_newProcess) { STARTUPINFOW si = { 0 }; si.cb = sizeof(si); if (!CreateProcessW( _procPath.c_str(), cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi )) { MessageBoxW( _hMainDlg, L"Failed to create new process", L"Error", MB_ICONERROR ); return GetLastError(); } thdId = 0; // Wait for process to initialize loader Sleep( 1 ); AttachToProcess( pi.dwProcessId ); } // Final sanity check if (ValidateImage( path.c_str(), init.c_str() ) != ERROR_SUCCESS) { if (_newProcess) TerminateProcess( pi.hProcess, 0 ); return ERROR_CANCELLED; } // Normal inject if (bManual == false) { if (_imagePE.IsPureManaged()) { DWORD code = 0; if (!_proc.modules().InjectPureIL( blackbone::ImageNET::GetImageRuntimeVer( path.c_str() ), path, blackbone::Utils::AnsiToWstring( init ), arg, code )) { if (_newProcess) TerminateProcess( pi.hProcess, 0 ); MessageBoxW( _hMainDlg, L"Failed to inject image", L"Error", MB_ICONERROR ); return ERROR_FUNCTION_FAILED; } } else if (!_newProcess && thdId != 0) { pThread = _proc.threads().get( thdId ); if (pThread == nullptr) { if (_newProcess) TerminateProcess( pi.hProcess, 0 ); MessageBoxW( _hMainDlg, L"Selected thread does not exist", L"Error", MB_ICONERROR ); return ERROR_NOT_FOUND; } // Load auto pLoadLib = _proc.modules().GetExport( _proc.modules().GetModule( L"kernel32.dll" ), "LoadLibraryW" ).procAddress; blackbone::RemoteFunction<decltype(&LoadLibraryW)> pfn( _proc, (decltype(&LoadLibraryW))pLoadLib, path.c_str() ); decltype(pfn)::ReturnType junk = 0; pfn.Call( junk, pThread ); mod = _proc.modules().GetModule( path ); } else mod = _proc.modules().Inject( path ); } // Manual map else { thdId = 0; int flags = blackbone::RebaseProcess | blackbone::NoDelayLoad | MmapFlags(); mod = _proc.mmap().MapImage( path, flags ); } if (mod == 0 && !_imagePE.IsPureManaged()) { if (_newProcess) TerminateProcess( pi.hProcess, 0 ); MessageBoxW( _hMainDlg, L"Failed to inject image", L"Error", MB_ICONERROR ); return ERROR_NOT_FOUND; } // Call init for native image if (!init.empty() && !_imagePE.IsPureManaged()) { auto fnPtr = _proc.modules().GetExport( mod, init.c_str() ).procAddress; if (thdId == 0) { auto argMem = _proc.memory().Allocate( 0x1000, PAGE_READWRITE ); argMem.Write( 0, arg.length() * sizeof(wchar_t)+2, arg.c_str() ); _proc.remote().ExecDirect( fnPtr, argMem.ptr() ); } else { pThread = _proc.threads().get( thdId ); if (pThread == nullptr) { if (_newProcess) TerminateProcess( pi.hProcess, 0 ); MessageBoxW( _hMainDlg, L"Selected thread does not exist", L"Error", MB_ICONERROR ); return ERROR_NOT_FOUND; } blackbone::RemoteFunction<int( _stdcall* )(const wchar_t*)> pfn( _proc, (int( _stdcall* )(const wchar_t*))fnPtr, arg.c_str() ); int junk = 0; pfn.Call( junk, pThread ); } } // Unlink module if required if (!_imagePE.IsPureManaged() && !bManual && Button_GetCheck( GetDlgItem( _hMainDlg, IDC_UNLINK ) )) if (_proc.modules().Unlink( mod ) == false) MessageBoxW( _hMainDlg, L"Failed to unlink module", L"Error", MB_ICONERROR ); // MessageBoxW( _hMainDlg, L"Successfully injected", L"Info", MB_ICONINFORMATION ); //ResumeThread( pi.hThread ); return ERROR_SUCCESS; }