address_translator() : enabled(true) { // Must have bounds filled with min ptr and max ptr to have search working properly map.insert(std::make_pair(raw_ptr(0x00000000u), raw_ptr(0x00000000u))); map.insert(std::make_pair(raw_ptr(0xffffffffu), raw_ptr(0xffffffffu))); add(); }
raw_ptr get(void) { throw std::runtime_error( Traits::translate( shared_data, "Copy construction not supported" ) ); return raw_ptr(); }
void dispatch(implementation_type& impl, Handler handler) { // If we are already in the strand then the handler can run immediately. if (call_stack<strand_impl>::contains(impl)) { boost::asio::detail::fenced_block b; boost_asio_handler_invoke_helpers::invoke(handler, handler); return; } // Allocate and construct an object to wrap the handler. typedef completion_handler<Handler> value_type; typedef handler_alloc_traits<Handler, value_type> alloc_traits; raw_handler_ptr<alloc_traits> raw_ptr(handler); handler_ptr<alloc_traits> ptr(raw_ptr, handler); // If we are running inside the io_service, and no other handler is queued // or running, then the handler can run immediately. bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_); impl->mutex_.lock(); bool first = (++impl->count_ == 1); if (can_dispatch && first) { // Immediate invocation is allowed. impl->mutex_.unlock(); // Memory must be releaesed before any upcall is made. ptr.reset(); // Indicate that this strand is executing on the current thread. call_stack<strand_impl>::context ctx(impl); // Ensure the next handler, if any, is scheduled on block exit. on_dispatch_exit on_exit = { &io_service_, impl }; (void)on_exit; boost::asio::detail::fenced_block b; boost_asio_handler_invoke_helpers::invoke(handler, handler); return; } // Immediate invocation is not allowed, so enqueue for later. impl->queue_.push(ptr.get()); impl->mutex_.unlock(); ptr.release(); // The first handler to be enqueued is responsible for scheduling the // strand. if (first) io_service_.post_immediate_completion(impl); }
inline void* address_translator_manager::translator(void* p_) { static const size_t max_ptr_dist = 7; // Tries to find an address in a translator map auto try_map = [](const std::map<memory_pointer_raw, memory_pointer_raw>& map, memory_pointer_raw p) -> memory_pointer_raw { memory_pointer_raw result = nullptr; // Find first element in the map that is greater than or equal to p auto it = map.lower_bound(p); if(it != map.end()) { // If it's not exactly the address, get back one position on the table if(it->first != p) --it; auto diff = (p - it->first).as_int(); // What's the difference between p and that address? if(diff <= max_ptr_dist) // Could we live with this difference in hands? result = it->second + raw_ptr(diff); // Yes, we can! } return result; }; // memory_pointer_raw result = nullptr; // Try to find translation for this pointer auto& mgr = address_translator_manager::singleton().translators; for(auto it = mgr.begin(); result == nullptr && it != mgr.end(); ++it) { auto& t = **it; if(t.is_enabled()) result = try_map(t.map, p_); } // If we couldn't translate the address, notify and try to fallback if(result.is_null()) { for(auto it = mgr.begin(); result == nullptr && it != mgr.end(); ++it) { auto& t = **it; if(t.is_enabled()) result = t.fallback(p_); } } return result.get(); }
// make a new copied instance if the type has a copy constructor static raw_ptr make_new_copy( raw_ptr source, std::true_type ) { // check the source assert(bool(source)); // cast and dereference the source pointer // and make a new instance using the copy // constructor original_type* tmp = new original_type( *(mirror::raw_cast< const original_type* >(source)) ); return raw_ptr(tmp); }
raw_ptr add_constructor( raw_ptr parent_data, const shared<meta_constructor>& constructor, const polymorph_factory_context& context, bool backward_iteration ) { // Let the helper take a look at the current constructor // and to update the index pick data helper.preview_constructor( constructor, ctx_data, idx_pick_data, backward_iteration ); return raw_ptr(&data); }
void post(implementation_type& impl, Handler handler) { // Allocate and construct an object to wrap the handler. typedef completion_handler<Handler> value_type; typedef handler_alloc_traits<Handler, value_type> alloc_traits; raw_handler_ptr<alloc_traits> raw_ptr(handler); handler_ptr<alloc_traits> ptr(raw_ptr, handler); // Add the handler to the queue. impl->mutex_.lock(); bool first = (++impl->count_ == 1); impl->queue_.push(ptr.get()); impl->mutex_.unlock(); ptr.release(); // The first handler to be enqueue is responsible for scheduling the strand. if (first) io_service_.post_immediate_completion(impl); }
raw_ptr data(void) { return raw_ptr(¶m); }
// Detects game, region and version; returns false if could not detect it inline bool game_version_manager::Detect() { // Cleanup data this->Clear(); // Find NT header uintptr_t base = (uintptr_t) GetModuleHandleA(NULL);; IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)(base); IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(base + dos->e_lfanew); // Look for game and version thought the entry-point // Thanks to Silent for many of the entry point offsets switch(base + nt->OptionalHeader.AddressOfEntryPoint) { case 0x5C1E70: // GTA III 1.0 game = '3', major = 1, minor = 0, region = 0, steam = false; return true; case 0x5C2130: // GTA III 1.1 game = '3', major = 1, minor = 1, region = 0, steam = false; return true; case 0x5C6FD0: // GTA III 1.1 (Cracked Steam Version) case 0x9912ED: // GTA III 1.1 (Encrypted Steam Version) game = '3', major = 1, minor = 1, region = 0, steam = true; return true; case 0x667BF0: // GTA VC 1.0 game = 'V', major = 1, minor = 0, region = 0, steam = false; return true; case 0x667C40: // GTA VC 1.1 game = 'V', major = 1, minor = 1, region = 0, steam = false; return true; case 0x666BA0: // GTA VC 1.1 (Cracked Steam Version) case 0xA402ED: // GTA VC 1.1 (Encrypted Steam Version) game = 'V', major = 1, minor = 1, region = 0, steam = true; return true; case 0x82457C: // GTA SA 1.0 US Cracked case 0x824570: // GTA SA 1.0 US Compact game = 'S', major = 1, minor = 0, region = 'U', steam = false; cracker = injector::ReadMemory<uint8_t>(raw_ptr(0x406A20), true) == 0xE9? 'H' : 0; return true; case 0x8245BC: // GTA SA 1.0 EU Cracked game = 'S', major = 1, minor = 0, region = 'E', steam = false; return true; case 0x8252FC: // GTA SA 1.1 US Cracked game = 'S', major = 1, minor = 1, region = 'U', steam = false; return true; case 0x82533C: // GTA SA 1.1 EU Cracked game = 'S', major = 1, minor = 1, region = 'E', steam = false; return true; case 0x85EC4A: // GTA SA 3.0 (Cracked Steam Version) case 0xD3C3DB: // GTA SA 3.0 (Encrypted Steam Version) game = 'S', major = 3, minor = 0, region = 0, steam = true; return true; default: return false; } }
// implementation of make_new for types without // a copy constructor static inline raw_ptr make_new_copy(raw_ptr, std::false_type) { return raw_ptr(); }
// implementation of make_new for types without // a default constructor static inline raw_ptr make_new(std::false_type) { return raw_ptr(); }
// make a new instance if the type has a default constructor static raw_ptr make_new(std::true_type) { original_type* tmp = new original_type(); return raw_ptr(tmp); }
void async_read_some_at(implementation_type& impl, boost::uint64_t offset, const MutableBufferSequence& buffers, Handler handler) { if (!is_open(impl)) { this->get_io_service().post(bind_handler(handler, boost::asio::error::bad_descriptor, 0)); return; } // Update the ID of the thread from which cancellation is safe. if (impl.safe_cancellation_thread_id_ == 0) impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) impl.safe_cancellation_thread_id_ = ~DWORD(0); // Allocate and construct an operation to wrap the handler. typedef read_operation<MutableBufferSequence, Handler> value_type; typedef handler_alloc_traits<Handler, value_type> alloc_traits; raw_handler_ptr<alloc_traits> raw_ptr(handler); handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler); // Find first buffer of non-zero length. boost::asio::mutable_buffer buffer; typename MutableBufferSequence::const_iterator iter = buffers.begin(); typename MutableBufferSequence::const_iterator end = buffers.end(); for (DWORD i = 0; iter != end; ++iter, ++i) { buffer = boost::asio::mutable_buffer(*iter); if (boost::asio::buffer_size(buffer) != 0) break; } // A request to receive 0 bytes on a stream handle is a no-op. if (boost::asio::buffer_size(buffer) == 0) { boost::asio::io_service::work work(this->get_io_service()); ptr.reset(); boost::system::error_code error; iocp_service_.post(bind_handler(handler, error, 0)); return; } // Read some data. DWORD bytes_transferred = 0; ptr.get()->Offset = offset & 0xFFFFFFFF; ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; BOOL ok = ::ReadFile(impl.handle_, boost::asio::buffer_cast<LPVOID>(buffer), static_cast<DWORD>(boost::asio::buffer_size(buffer)), &bytes_transferred, ptr.get()); DWORD last_error = ::GetLastError(); if (!ok && last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA) { boost::asio::io_service::work work(this->get_io_service()); ptr.reset(); boost::system::error_code ec(last_error, boost::asio::error::get_system_category()); iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); } else { ptr.release(); } }
raw_ptr get(void) { assert(!"No external sources available"); return raw_ptr(); }
// Restores the previous call before the hook happened static void restore() { MakeCALL(addr, raw_ptr(original())); }
// Constructs passing information to the static variables function_hooker(hook_type hooker) { hook() = hooker; original() = MakeCALL(addr, raw_ptr(call)).get(); }