#pragma once
// #include <istream>
// #include <fstream>
// #include <vector>
#include <string>
// #include <sstream>
// #include <Psapi.h>
// #include <iterator>
#include <Windows.h>
// #include <assert.h>
// #include <iostream>
// #include <algorithm>

#include <Psapi.h>

// enum EPagePermissions
// {
// 	Execute = PAGE_EXECUTE,
// 	ExecuteRead = PAGE_EXECUTE_READ,
// 	ExecuteReadWrite = PAGE_EXECUTE_READWRITE,
// 	ExecuteWriteCopy = PAGE_EXECUTE_WRITECOPY,
// 	Read = PAGE_READONLY,
// 	ReadWrite = PAGE_READWRITE,
// 	WriteCopy = PAGE_WRITECOPY,
// 	WriteCombine = PAGE_WRITECOMBINE
// };

// struct PatternInfo
// {
// 	const char *Pattern;
// 	EPagePermissions Permissions;
// };

namespace PatternScan
{
	// 	struct PatternByte
	// 	{
	// 		struct PatternNibble
	// 		{
	// 			unsigned char data;
	// 			bool wildcard;
	// 		} nibble[2];
	// 	};

	// 	static std::string formathexpattern(std::string patterntext)
	// 	{
	// 		std::string result;
	// 		int len = patterntext.length();
	// 		for (int i = 0; i < len; i++)
	// 			if (patterntext[i] == '?' || isxdigit(patterntext[i]))
	// 				result += toupper(patterntext[i]);
	// 		return result;
	// 	}

	// 	static int hexchtoint(char ch)
	// 	{
	// 		if (ch >= '0' && ch <= '9')
	// 			return ch - '0';
	// 		else if (ch >= 'A' && ch <= 'F')
	// 			return ch - 'A' + 10;
	// 		else if (ch >= 'a' && ch <= 'f')
	// 			return ch - 'a' + 10;
	// 		return 0;
	// 	}

	// 	static bool patterntransform(std::string patterntext, std::vector<PatternByte> &pattern)
	// 	{
	// 		pattern.clear();
	// 		patterntext = formathexpattern(patterntext);
	// 		int len = patterntext.length();
	// 		if (!len)
	// 			return false;

	// 		if (len % 2) //not a multiple of 2
	// 		{
	// 			patterntext += '?';
	// 			len++;
	// 		}

	// 		PatternByte newByte;
	// 		for (int i = 0, j = 0; i < len; i++)
	// 		{
	// 			if (patterntext[i] == '?') //wildcard
	// 			{
	// 				newByte.nibble[j].wildcard = true; //match anything
	// 			}
	// 			else //hex
	// 			{
	// 				newByte.nibble[j].wildcard = false;
	// 				newByte.nibble[j].data = hexchtoint(patterntext[i]) & 0xF;
	// 			}

	// 			j++;
	// 			if (j == 2) //two nibbles = one byte
	// 			{
	// 				j = 0;
	// 				pattern.push_back(newByte);
	// 			}
	// 		}
	// 		return true;
	// 	}

	// 	static bool patternmatchbyte(unsigned char byte, const PatternByte &pbyte)
	// 	{
	// 		int matched = 0;

	// 		unsigned char n1 = (byte >> 4) & 0xF;
	// 		if (pbyte.nibble[0].wildcard)
	// 			matched++;
	// 		else if (pbyte.nibble[0].data == n1)
	// 			matched++;

	// 		unsigned char n2 = byte & 0xF;
	// 		if (pbyte.nibble[1].wildcard)
	// 			matched++;
	// 		else if (pbyte.nibble[1].data == n2)
	// 			matched++;

	// 		return (matched == 2);
	// 	}

	// 	size_t patternfind(std::string pattern, int offset)
	// 	{
	// 		std::vector<PatternByte> searchpattern;

	// 		std::string::iterator end_pos = std::remove(pattern.begin(), pattern.end(), ' ');
	// 		pattern.erase(end_pos, pattern.end());

	// 		SYSTEM_INFO sysinf;
	// 		GetSystemInfo(&sysinf);

	// 		DWORD startAddress = (DWORD)sysinf.lpMinimumApplicationAddress;

	// 		unsigned char *data = (unsigned char *)startAddress;

	// 		//MEMORY_BASIC_INFORMATION mbi;

	// 		if (!patterntransform(pattern.c_str(), searchpattern))
	// 			return (size_t)-1;

	// 		//#define MEMORY_READABLE        (PAGE_READONLY    | PAGE_READWRITE    | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)
	// 		//#define MEMORY_WRITABLE        (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)
	// 		//#define MEMORY_EXECUTABLE    (PAGE_EXECUTE    | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)
	// 		size_t searchpatternsize = searchpattern.size();
	// 		for (size_t i = 0, pos = 0; i < 0x7FFFFFFF; i++) //search for the pattern
	// 		{
	// 			//if (VirtualQuery((LPVOID)i, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0
	// 			//	&& ((mbi.State != MEM_COMMIT) || !(mbi.Protect & MEMORY_READABLE) || (mbi.Protect & PAGE_GUARD)))
	// 			//	//&& mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && !(mbi.Protect & PAGE_GUARD))
	// 			//{
	// 			if (patternmatchbyte(data[i], searchpattern.at(pos))) //check if our pattern matches the current byte
	// 			{
	// 				pos++;
	// 				if (pos == searchpatternsize) //everything matched
	// 				{
	// 					if (offset >= 0)
	// 						return startAddress + i - searchpatternsize + 1 + offset;
	// 					if (offset < 0)
	// 						return startAddress + i - searchpatternsize + 1 - offset;
	// 				}
	// 			}
	// 			else if (pos > 0) //fix by Computer_Angel
	// 			{
	// 				i -= pos;
	// 				pos = 0; //reset current pattern position
	// 			}
	// 			/*}
	// 			else
	// 				i += mbi.RegionSize;*/
	// 		}
	// 		return (size_t)-1;
	// 	}

	// 	// Find all occurences of the Pattern until a wildcard is hit
	// 	std::vector<uintptr_t> FindAllOccurences(std::vector<char *> pattern, std::vector<char> streamToSearch)
	// 	{
	// 		std::vector<uintptr_t> positions;

	// 		// Length of the pattern to look for
	// 		unsigned int patternLength = pattern.size();

	// 		// Total length of file to look through
	// 		unsigned int totalLength = streamToSearch.size();

	// 		// First Byte of the pattern to look for
	// 		//unsigned char* firstMatchByte;
	// 		auto firstMatchByte = std::strtol(reinterpret_cast<const char *>(pattern[0]), nullptr, 16);
	// 		std::vector<unsigned char> parsedPattern;
	// 		parsedPattern.reserve(pattern.size());
	// 		for (auto &pat : pattern)
	// 		{
	// 			parsedPattern.push_back((unsigned char)std::strtoul(reinterpret_cast<const char *>(pat), nullptr, 16));
	// 		}

	// 		for (unsigned int i = 0; i < totalLength; i++)
	// 		{
	// 			//auto cmp = (unsigned char)streamToSearch[i];
	// 			//auto cmp2 = (unsigned char)firstMatchByte;
	// 			//auto cmp2 = std::strtol(reinterpret_cast<const char*>(streamToSearch.data()[i]), nullptr, 16);
	// 			//auto second = streamToSearch;
	// 			//memcpy(&firstMatchByte, streamToSearch[i], sizeof (unsigned char*));
	// 			// If the first Byte of the Searchpattern is at the current location of i
	// 			// and the totalLength - i is greater or equal to the pattern length
	// 			//if(i == 0x00000000000dca41)
	// 			//{
	// 			//Q_ASSERT(false);
	// 			//}
	// 			if ((unsigned char)streamToSearch[i] == firstMatchByte && totalLength - i >= patternLength)
	// 			//if (pattern.data()[0] == *(streamToSearch.begin() +i) && totalLength - i >= patternLength)
	// 			{
	// 				std::vector<unsigned char> match; //[patternLength];
	// 				match.resize(patternLength);
	// 				memcpy(&match[0], &streamToSearch[i], patternLength);

	// 				// If the current range of the search matches the searchPattern
	// 				// add the current position(i) to the positionList and break
	// 				if (memcmp(match.data(), parsedPattern.data(), patternLength) == 0)
	// 				{
	// 					positions.push_back(static_cast<uintptr_t>(i));
	// 				}
	// 				else
	// 				{
	// 					memset(&match, 0, patternLength);
	// 				}
	// 			}
	// 		}
	// 		return positions;
	// 	}

	// 	// Find all occurences of the Pattern until a wildcard is hit
	// 	std::vector<uintptr_t> FindAllOccurences(std::vector<char *> pattern, uintptr_t startAddress, uintptr_t totalSize = 0x7FFFFFFF)
	// 	{
	// 		std::vector<uintptr_t> positions;

	// 		// Length of the pattern to look for
	// 		unsigned int patternLength = pattern.size();

	// 		// Total length of file to look through
	// 		unsigned int totalLength = totalSize - startAddress;

	// 		// First Byte of the pattern to look for
	// 		//unsigned char* firstMatchByte;
	// 		auto firstMatchByte = std::strtol(reinterpret_cast<const char *>(pattern[0]), nullptr, 16);
	// 		std::vector<unsigned char> parsedPattern;
	// 		parsedPattern.reserve(pattern.size());

	// 		for (auto &pat : pattern)
	// 		{
	// 			parsedPattern.push_back((unsigned char)std::strtol(reinterpret_cast<const char *>(pat), nullptr, 16));
	// 		}

	// 		for (unsigned int i = 0; i < totalLength; i++)
	// 		{
	// 			if ((*(PBYTE)startAddress + i) == firstMatchByte && totalLength - i >= patternLength)
	// 			{
	// 				std::vector<unsigned char> match; //[patternLength];
	// 				match.resize(patternLength);
	// 				memcpy(&match[0], (LPVOID)(*(PBYTE)startAddress + i), patternLength);

	// 				// If the current range of the search matches the searchPattern
	// 				// add the current position(i) to the positionList and break
	// 				if (memcmp(match.data(), parsedPattern.data(), patternLength) == 0)
	// 				{
	// 					positions.push_back(static_cast<uintptr_t>(i));
	// 				}
	// 				else
	// 				{
	// 					memset(&match, 0, patternLength);
	// 				}
	// 			}
	// 		}
	// 		return positions;
	// 	}

	// 	// Search the given Pattern iconst n the given& char-vector
	// 	uintptr_t SearchBytePattern(const std::string &pattern, std::vector<char> streamToSearch, int offset)
	// 	{
	// 		std::istringstream buf(pattern);
	// 		std::istream_iterator<std::string> beg(buf), end;
	// 		std::vector<std::string> tokens(beg, end);
	// 		std::vector<char *> patternArray;
	// 		patternArray.reserve(tokens.size());
	// 		for (auto &data : tokens)
	// 		{
	// 			patternArray.push_back(_strdup(data.c_str()));
	// 		}

	// 		std::vector<char *> temp;

	// 		for (unsigned int i = 0; i < tokens.size(); i++)
	// 		{
	// 			// Using QString for the "startsWith function
	// 			// auto value = QString(patternArray[i]);
	// 			// if(!value.startsWith('?', Qt::CaseInsensitive))
	// 			auto value = std::string(patternArray[i]);
	// 			if (!_strnicmp(value.c_str(), "?", sizeof("?")))
	// 			{
	// 				temp.push_back(patternArray[i]);
	// 			}
	// 			else
	// 				break;
	// 		}

	// 		auto occurences = FindAllOccurences(temp, streamToSearch);

	// 		std::vector<unsigned char> parsedPattern;
	// 		parsedPattern.reserve(patternArray.size());
	// 		for (auto &pat : patternArray)
	// 		{
	// 			parsedPattern.push_back((unsigned char)std::strtol(reinterpret_cast<const char *>(pat), nullptr, 16));
	// 		}

	// 		std::vector<char> check(patternArray.size());
	// 		for (auto &occ : occurences)
	// 		{
	// 			memset(check.data(), 0, patternArray.size());
	// 			memcpy(check.data(), &streamToSearch[occ], patternArray.size());

	// 			for (unsigned int o = 0; o < patternArray.size(); o++)
	// 			{
	// 				// If the current Patterncharacter is a wildcard, go to next index
	// 				if (isalnum(*patternArray[o]) == 0) // == 0 || isalpha(*patternArray[0]) == 0)
	// 					continue;

	// 				// Convert current Patternindex
	// 				char pat = (char)std::stoul(std::string(patternArray[o]), nullptr, 16);

	// 				// Compare memory, if equal, result is 0
	// 				int mem = memcmp(&check[o], &pat, 1);

	// 				// If memory is not equal, the pattern doesn't match
	// 				if (mem != 0)
	// 				{
	// 					break;
	// 				}
	// 				// o can only be the size of the pattern if it matches
	// 				if (o == patternArray.size() - 1)
	// 				{
	// 					if (offset < 0)
	// 						return occ - offset;
	// 					if (offset > 0)
	// 						return occ + offset;
	// 					return occ;
	// 				}
	// 			}
	// 		}
	// 		// No result found
	// 		return 0;
	// 	}

	// 	uintptr_t SearchBytePattern(uintptr_t startAddress, uintptr_t fileSize, const std::string &pattern, int offset)
	// 	{
	// 		MODULEINFO miInfos = {NULL};
	// 		HMODULE hmModule = GetModuleHandle(NULL);

	// 		if (hmModule)
	// 		{
	// 			GetModuleInformation(GetCurrentProcess(), hmModule, &miInfos, sizeof(MODULEINFO));
	// 		}

	// 		std::istringstream buf(pattern);
	// 		std::istream_iterator<std::string> beg(buf), end;
	// 		std::vector<std::string> tokens(beg, end);
	// 		std::vector<char *> patternArray;
	// 		patternArray.reserve(tokens.size());
	// 		for (auto &data : tokens)
	// 		{
	// 			patternArray.push_back(_strdup(data.c_str()));
	// 		}

	// 		std::vector<char *> temp;

	// 		for (unsigned int i = 0; i < tokens.size(); i++)
	// 		{
	// 			// Using QString for the "startsWith function
	// 			auto value = std::string(patternArray[i]);
	// 			if (_strnicmp(value.c_str(), "?", sizeof("?")))
	// 			{
	// 				temp.push_back(patternArray[i]);
	// 			}
	// 			else
	// 				break;
	// 		}

	// 		auto occurences = FindAllOccurences(temp, startAddress);

	// 		std::vector<unsigned char> parsedPattern;
	// 		parsedPattern.reserve(patternArray.size());
	// 		for (auto &pat : patternArray)
	// 		{
	// 			parsedPattern.push_back((unsigned char)std::strtol(reinterpret_cast<const char *>(pat), nullptr, 16));
	// 		}

	// 		std::vector<char> check(patternArray.size());
	// 		for (auto &occ : occurences)
	// 		{
	// 			memset(check.data(), 0, patternArray.size());
	// 			memcpy(check.data(), (LPVOID)(startAddress + occ), patternArray.size());

	// 			for (unsigned int o = 0; o < patternArray.size(); o++)
	// 			{
	// 				// If the current Patterncharacter is a wildcard, go to next index
	// 				if (isalnum(*patternArray[o]) == 0) // == 0 || isalpha(*patternArray[0]) == 0)
	// 					continue;

	// 				// Convert current Patternindex
	// 				char pat = (char)std::stoul(std::string(patternArray[o]), nullptr, 16);

	// 				// Compare memory, if equal, result is 0
	// 				int mem = memcmp(&check[o], &pat, 1);

	// 				// If memory is not equal, the pattern doesn't match
	// 				if (mem != 0)
	// 				{
	// 					break;
	// 				}
	// 				// o can only be the size of the pattern if it matches
	// 				if (o == patternArray.size() - 1)
	// 				{
	// 					if (offset < 0)
	// 						return occ - offset;
	// 					if (offset > 0)
	// 						return occ + offset;
	// 					return occ;
	// 				}
	// 			}
	// 		}
	// 		// No result found
	// 		return 0;
	// 	}

	// 	/**
	// 	* \brief Returns first occurrence of byte pattern in a module
	// 	* \param module Base address of module
	// 	* \param signature IDA-style byte pattern
	// 	* \return Pointer to first occurrence
	// 	* \see CSGOSimple by MarkHC
	// 	*/
	// 	inline std::uint8_t *patternScan(void *module, std::string signature)
	// 	{
	// 		static auto pattern_to_byte = [](const char *pattern) {
	// 			auto bytes = std::vector<int>{};
	// 			auto start = const_cast<char *>(pattern);
	// 			auto end = const_cast<char *>(pattern) + strlen(pattern);

	// 			for (auto current = start; current < end; ++current)
	// 			{
	// 				if (*current == '??')
	// 				{
	// 					++current;
	// 					if (*current == '??')
	// 						++current;
	// 					bytes.push_back(-1);
	// 				}
	// 				else
	// 					bytes.push_back(strtoul(current, &current, 16));
	// 			}
	// 			return bytes;
	// 		};

	// 		auto dosHeader = (PIMAGE_DOS_HEADER)module;
	// 		auto ntHeaders = (PIMAGE_NT_HEADERS)((std::uint8_t *)module + dosHeader->e_lfanew);

	// 		auto sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
	// 		auto patternBytes = pattern_to_byte(signature.c_str());
	// 		auto scanBytes = reinterpret_cast<std::uint8_t *>(module);

	// 		auto s = patternBytes.size();
	// 		auto d = patternBytes.data();

	// 		for (auto i = 0ul; i < sizeOfImage - s; ++i)
	// 		{
	// 			bool found = true;
	// 			for (auto j = 0ul; j < s; ++j)
	// 			{
	// 				if (scanBytes[i + j] != d[j] && d[j] != -1)
	// 				{
	// 					found = false;
	// 					break;
	// 				}
	// 			}
	// 			if (found)
	// 				return &scanBytes[i];
	// 		}

	// 		return nullptr;
	// 	}

	// 	static std::vector<unsigned char> ParseSignature(std::string &pattern)
	// 	{
	// 		std::vector<unsigned char> bytes;
	// 		for (unsigned int i = 0; i < pattern.length(); i += 2)
	// 		{
	// 			std::string byteString = pattern.substr(i, 2);
	// 			char byte = (char)strtol(byteString.c_str(), NULL, 16);
	// 			bytes.push_back(byte);
	// 		}
	// 		return bytes;
	// 	}

	// 	static DWORD FindMySignature(const char *szModule, std::string szSignature, int offset)
	// 	{
	// 		/*AllocConsole();
	// 		freopen("CONIN$", "r", stdin);
	// 		freopen("CONOUT$", "w", stdout);
	// 		freopen("CONOUT$", "w", stderr);*/

	// 		MODULEINFO modInfo;
	// 		GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &modInfo, sizeof(MODULEINFO));
	// 		DWORD startAddress = (DWORD)modInfo.lpBaseOfDll;
	// 		DWORD endAddress = startAddress + modInfo.SizeOfImage;

	// 		std::string pattern = szSignature;
	// 		std::string::iterator end_pos = std::remove(szSignature.begin(), szSignature.end(), ' ');
	// 		szSignature.erase(end_pos, szSignature.end());

	// 		//const char* pat = szSignature.c_str();
	// 		auto pat = ParseSignature(szSignature);

	// 		DWORD firstMatch = 0;

	// 		//std::vector<char> check(sizeof(szSignature));
	// 		//auto firstMatchByte = std::strtol(&pat[0], nullptr, 16);
	// 		auto firstMatchByte = (int)pat[0];
	// 		std::cout << std::hex << (int)*(unsigned char *)startAddress << '\n';
	// 		std::cout << "Pattern to search for: " << szSignature << '\n';
	// 		std::cout << "Length of Pattern: " << szSignature.length() << '\n';
	// 		std::cout << "FirstMatchByte: " << std::hex << firstMatchByte << '\n';

	// 		SYSTEM_INFO sysinf;
	// 		GetSystemInfo(&sysinf);

	// 		MEMORY_BASIC_INFORMATION mbi;
	// 		//startAddress += 0x4F318C;

	// 		/*for (int i = 0; i < pat.size(); i++)
	// 			std::cout << (int)pat[i];*/

	// 		for (DWORD pCur = startAddress; pCur < 0x7FFFFFFF; pCur++)
	// 		{
	// 			if (VirtualQuery((LPVOID)pCur, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0
	// 				//&& ((mBI.State != MEM_COMMIT) || !(mBI.Protect & MEMORY_READABLE) || (mBI.Protect & PAGE_GUARD)))
	// 				&& mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && !(mbi.Protect & PAGE_GUARD))
	// 			{

	// 				//CREDITS: learn_more
	// #define INRANGE(x, a, b) (x >= a && x <= b)
	// #define getBits(x) (INRANGE((x & (~0x20)), 'A', 'F') ? ((x & (~0x20)) - 'A' + 0xa) : (INRANGE(x, '0', '9') ? x - '0' : 0))
	// #define getByte(x) (getBits(x[0]) << 4 | getBits(x[1]))

	// 				const char *patt = pattern.c_str();

	// 				if (!*patt)
	// 					return firstMatch;
	// 				if (*(PBYTE)patt == '\?' || *(BYTE *)pCur == getByte(patt))
	// 				{
	// 					if (!firstMatch)
	// 						firstMatch = pCur;
	// 					if (!patt[2])
	// 						return firstMatch;
	// 					if (*(PWORD)patt == '\?\?' || *(PBYTE)patt != '\?')
	// 						patt += 3;
	// 					else
	// 						patt += 2; //one ?
	// 				}
	// 				else
	// 				{
	// 					patt = szSignature.c_str();
	// 					firstMatch = 0;
	// 				}

	// 				if ((int)*(unsigned char *)pCur == (int)firstMatchByte && endAddress - pCur >= szSignature.length())
	// 				{
	// 					//if (pattern.data()[0] == *(streamToSearch.begin() +i) && totalLength - i >= patternLength)
	// 					for (unsigned int o = 0; o < pat.size(); o++)
	// 					{
	// 						// If the current Patterncharacter is a wildcard, go to next index
	// 						//if (isalnum(szSignature[o]) == 0)// == 0 || isalpha(*patternArray[0]) == 0)
	// 						if (pat[o] == strtol("??", 0, 16))
	// 						{
	// 							//std::cout << "Current Patternindex is a wildcard: " << pat[o] << '\n';
	// 							continue;
	// 						}

	// 						auto currentPat = (int)pat[o];

	// 						/*std::cout << '\n\n';
	// 						std::cout << "Startaddress: 0x" << std::hex << (DWORD)modInfo.lpBaseOfDll << '\n';
	// 						std::cout << "Currentaddress: 0x" << std::hex << pCur + o << '\n';
	// 						std::cout << "Current Byte is: " << std::hex << (int)*(unsigned char*)(pCur + o) << '\n';
	// 						std::cout << "Current Pattern is: " << std::hex << currentPat << '\n';
	// 						std::cout << '\n';*/

	// 						if ((int)*(unsigned char *)(pCur + o) != currentPat)
	// 						{
	// 							//std::cout << "Cur Val: 0x" << std::hex << (int)*(unsigned char*)(pCur + o) << " Pattern: 0x" << std::hex << currentPat << '\n';
	// 							break;
	// 						}

	// 						// o can only be the size of the pattern if it matches
	// 						if (o == pat.size() - 1)
	// 						{
	// 							if (offset < 0)
	// 								return pCur - offset;
	// 							if (offset > 0)
	// 								return pCur + offset;
	// 							return pCur;
	// 						}
	// 					}
	// 				}
	// 			}
	// 			else
	// 				pCur += mbi.RegionSize;
	// 		}
	// 		return NULL;
	// 	}

	static uintptr_t FindSignature(const char *szModule, const char *szSignature)
	{
		//CREDITS: learn_more
#define INRANGE(x, a, b) (x >= a && x <= b)
#define getBits(x) (INRANGE((x & (~0x20)), 'A', 'F') ? ((x & (~0x20)) - 'A' + 0xa) : (INRANGE(x, '0', '9') ? x - '0' : 0))
#define getByte(x) (getBits(x[0]) << 4 | getBits(x[1]))

		MODULEINFO modInfo;
		GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &modInfo, sizeof(MODULEINFO));
		uintptr_t startAddress = (uintptr_t)modInfo.lpBaseOfDll;
		uintptr_t endAddress = startAddress + modInfo.SizeOfImage;
		const char *pat = szSignature;
		uintptr_t firstMatch = 0;
		for (uintptr_t pCur = startAddress; pCur < endAddress; pCur++)
		{
			if (!*pat)
				return firstMatch;
			if (*(PBYTE)pat == '\?' || *(BYTE *)pCur == getByte(pat))
			{
				if (!firstMatch)
					firstMatch = pCur;
				if (!pat[2])
					return firstMatch;
				if (*(PWORD)pat == '\?\?' || *(PBYTE)pat != '\?')
				//if (*(PWORD)pat == '\?' || *(PBYTE)pat != '\?')
					pat += 3;
				else
					pat += 2; //one ?
			}
			else
			{
				pat = szSignature;
				firstMatch = 0;
			}
		}
		return 0;
	}
} // namespace PatternScan