text: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
   
  #include <iostream>  
  #include <io.h>  
  #include <Windows.h>  
  #include <cstdint>
  #include <memory>
  #include <vector>
  #include <string>
  #include <iostream>
  #include <fstream>
  
  #define  IMAGE_SIZEOF_SIGNATURE 4
  
  
  DWORD rva_to_foa(IN DWORD RVA, IN PIMAGE_SECTION_HEADER section_header) 
  {
  
  	size_t count = 0;
  	for (count = 1; RVA > (section_header->VirtualAddress + section_header->Misc.VirtualSize); count++, section_header++);
  
  	DWORD FOA = RVA - section_header->VirtualAddress + section_header->PointerToRawData;
  
  	return FOA;
  } 
  
  std::string format(const char* format, ...)
  {
  	va_list args;
  	va_start(args, format);
  #ifndef _MSC_VER
  	size_t size = std::snprintf(nullptr, 0, format, args) + 1; // Extra space for '\0'
  	std::unique_ptr<char[]> buf(new char[size]);
  	std::vsnprintf(buf.get(), size, format, args);
  	return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
  #else
  	int size = _vscprintf(format, args) +1;
  	std::unique_ptr<char[]> buf(new char[size]);
  	vsnprintf_s(buf.get(), size, _TRUNCATE, format, args);
  	return std::string(buf.get());
  #endif
  	va_end(args);
  }
  
  int main(int argc, char* argv[])
  {
  
  	if (argc != 2)
  	{
  		return 0;
  	}
  
  	//open file
  	const HANDLE h_file = CreateFile(
  		argv[1],   
  		GENERIC_READ , 
  		FILE_SHARE_READ ,
  		nullptr,
  		OPEN_EXISTING,  
  		FILE_ATTRIBUTE_NORMAL,
  		nullptr);
  
  
  	DWORD size_high;
  	const DWORD size_low = GetFileSize(h_file, &size_high);
  
  	uint64_t dll_size = ((uint64_t(size_high)) << 32) + (uint64_t)size_low;
  
  	// Create File Mapping
  	const HANDLE h_map_file = CreateFileMapping(
  		h_file,
  		nullptr,
  		PAGE_READONLY, 
  		size_high,
  		size_low,   
  		nullptr);
  	if (h_map_file == INVALID_HANDLE_VALUE || h_map_file == nullptr)
  	{
  		std::cout << "error";
  		CloseHandle(h_file);
  		return 0;
  	}
  
  	//Map File to memory
  	void* pv_file = MapViewOfFile(
  		h_map_file,
  		FILE_MAP_READ,
  		0,
  		0,
  		0);
  
  	if (pv_file == nullptr)
  	{
  		std::cout << "error";
  		CloseHandle(h_file);
  		return 0;
  	}
  
  	uint8_t* p = static_cast<uint8_t*>(pv_file);
  
  
  	PIMAGE_DOS_HEADER dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(p);
  
  	const PIMAGE_NT_HEADERS nt_headers = reinterpret_cast<const PIMAGE_NT_HEADERS>(p + dos_header->e_lfanew);
  
  	const PIMAGE_FILE_HEADER file_header = &nt_headers->FileHeader;
  
  	PIMAGE_OPTIONAL_HEADER	optional_header = (PIMAGE_OPTIONAL_HEADER)(&nt_headers->OptionalHeader);
  
  	const DWORD file_alignment = optional_header->FileAlignment;
  
  
  	PIMAGE_SECTION_HEADER section_table =
  		reinterpret_cast<PIMAGE_SECTION_HEADER>(p + dos_header->e_lfanew +
  			IMAGE_SIZEOF_SIGNATURE +
  			IMAGE_SIZEOF_FILE_HEADER +
  			file_header->SizeOfOptionalHeader);
  
  	DWORD	export_foa = rva_to_foa(optional_header->DataDirectory[0].VirtualAddress, section_table);
  
  	PIMAGE_EXPORT_DIRECTORY export_directory = (PIMAGE_EXPORT_DIRECTORY)(p + export_foa);
  
  
  	DWORD name_list_foa = rva_to_foa(export_directory->AddressOfNames, section_table);
  
  	PDWORD name_list = (PDWORD)(p + name_list_foa);
  
  
  
  
  	std::vector<std::string> func_list;
  
  	for (size_t i = 0; i < export_directory->NumberOfNames; i++, name_list++)
  	{
  
  		DWORD name_foa = rva_to_foa(* name_list, section_table);
  		char* name = (char*)(p + name_foa);
  		func_list.emplace_back(name);
  
  	}
  
  
  	UnmapViewOfFile(pv_file); 
  	CloseHandle(h_map_file);
  	CloseHandle(h_file); 
  
  
  	std::ofstream gen_cpp_obj;
  	gen_cpp_obj.open("warp_gen_cpp.cpp", std::ios::out | std::ios::trunc);
  	gen_cpp_obj << "#include <Windows.h>\n";
  	gen_cpp_obj << "extern \"C\" \n{\n";
  
  
  	for (size_t i = 0; i < func_list.size(); ++i)
  	{
  		auto fun = func_list[i];
  		gen_cpp_obj << format("void * warp_point_%d;\n", i);
  		gen_cpp_obj << format("#pragma comment(linker, \"/export:%s=warp_func_%d\")\n", fun.c_str(), i);
  		gen_cpp_obj << format("void warp_func_%d();\n", i);
  		gen_cpp_obj << ("\n");
  	}
  	gen_cpp_obj << ("}\n");
  
  
  	gen_cpp_obj << ("void load_function(HMODULE hm)\n{\n");
  	for (size_t i = 0; i < func_list.size(); ++i)
  	{
  		auto fun = func_list[i];
  		gen_cpp_obj << format("warp_point_%d = (void*)GetProcAddress(hm, \"%s\");\n", i, fun.c_str());
  	}
  	gen_cpp_obj << ("}\n");
  
  	gen_cpp_obj.close();
  
  
  
  	std::ofstream gen_asm_obj;
  	gen_asm_obj.open("warp_gen.asm", std::ios::out | std::ios::trunc);
  	for (size_t i = 0; i < func_list.size(); ++i)
  	{
  		auto fun = func_list[i];
  		gen_asm_obj << format("EXTERN warp_point_%d:QWORD;\n", i);
  	}
  	gen_asm_obj << ".CODE\n";
  	for (size_t i = 0; i < func_list.size(); ++i)
  	{
  		auto fun = func_list[i];
  		gen_asm_obj << format("warp_func_%d PROC\njmp warp_point_%d;\nwarp_func_%d ENDP\n", i,i,i);
  	}
  	gen_asm_obj << "END\n";
  	gen_asm_obj.close();
  }
  