#include "precomp.h"
#pragma hdrstop
#include <wincrypt.h>
#include <crypto/md5.h>
#include "bios.h"
#include "bl.h"
#include "crypthelper.h"
#include "../include/trivialencrypt.h"
#include "../include/certchain.h"

extern const BYTE unk_1019768[16] = {0xCC, 0xC3, 0x8B, 0xFF, 0xCC, 0xC3, 0x8B, 0xFF, 0x8B, 0x44, 0x24, 0x04, 0xCC, 0xC2, 0x04, 0};
extern const BYTE dword_1019778[16] = {0x8B, 0xFA, 0x8C, 0xC9, 0xFF, 0x33, 0xC0, 0xF2, 0xAE, 0xF7, 0xD1, 0x49, 0x8B, 0xF1, 0x98, 0x42};

// L"BIOS"
WCHAR word_10759B4[] = {0x1F61,0xE37F,0x7ABB,0xD447,0x793E,0x2CCC,0xF980};
// L"BIOS%d"
WCHAR word_10759C4[] = {0xFF61,0xC02F,0x0454,0x1C88,0x2E3B,0x1EEE,0x6B29,0xE5E0,0x3054};

DWORD sub_104C095(LPCVOID pbData, DWORD cbData, CONST BYTE* pbSignature, DWORD cbSignature, const BYTE* lpCertChain, DWORD cbCertChain) {
	HCRYPTPROV hProv = NULL;
	HCRYPTKEY hKey = 0;
	HCRYPTHASH hHash = 0;
	CONST BYTE RootCertEncoded[] = {
0x30,0x82,0x04,0x12,0x30,0x82,0x02,0xFA,0xA0,0x03,0x02,0x01,0x02,0x02,0x0F,0x00,
0xC1,0x00,0x8B,0x3C,0x3C,0x88,0x11,0xD1,0x3E,0xF6,0x63,0xEC,0xDF,0x40,0x30,0x0D,
0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,0x30,0x70,0x31,
0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x0B,0x13,0x22,0x43,0x6F,0x70,0x79,0x72,0x69,
0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x37,0x20,0x4D,0x69,0x63,
0x72,0x6F,0x73,0x6F,0x66,0x74,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x1E,0x30,0x1C,
0x06,0x03,0x55,0x04,0x0B,0x13,0x15,0x4D,0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,
0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x21,0x30,0x1F,
0x06,0x03,0x55,0x04,0x03,0x13,0x18,0x4D,0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,
0x20,0x52,0x6F,0x6F,0x74,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,
0x1E,0x17,0x0D,0x39,0x37,0x30,0x31,0x31,0x30,0x30,0x37,0x30,0x30,0x30,0x30,0x5A,
0x17,0x0D,0x32,0x30,0x31,0x32,0x33,0x31,0x30,0x37,0x30,0x30,0x30,0x30,0x5A,0x30,
0x70,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x0B,0x13,0x22,0x43,0x6F,0x70,0x79,
0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x37,0x20,0x4D,
0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x1E,
0x30,0x1C,0x06,0x03,0x55,0x04,0x0B,0x13,0x15,0x4D,0x69,0x63,0x72,0x6F,0x73,0x6F,
0x66,0x74,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x21,
0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x13,0x18,0x4D,0x69,0x63,0x72,0x6F,0x73,0x6F,
0x66,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,
0x79,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,
0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,
0x01,0x00,0xA9,0x02,0xBD,0xC1,0x70,0xE6,0x3B,0xF2,0x4E,0x1B,0x28,0x9F,0x97,0x78,
0x5E,0x30,0xEA,0xA2,0xA9,0x8D,0x25,0x5F,0xF8,0xFE,0x95,0x4C,0xA3,0xB7,0xFE,0x9D,
0xA2,0x20,0x3E,0x7C,0x51,0xA2,0x9B,0xA2,0x8F,0x60,0x32,0x6B,0xD1,0x42,0x64,0x79,
0xEE,0xAC,0x76,0xC9,0x54,0xDA,0xF2,0xEB,0x9C,0x86,0x1C,0x8F,0x9F,0x84,0x66,0xB3,
0xC5,0x6B,0x7A,0x62,0x23,0xD6,0x1D,0x3C,0xDE,0x0F,0x01,0x92,0xE8,0x96,0xC4,0xBF,
0x2D,0x66,0x9A,0x9A,0x68,0x26,0x99,0xD0,0x3A,0x2C,0xBF,0x0C,0xB5,0x58,0x26,0xC1,
0x46,0xE7,0x0A,0x3E,0x38,0x96,0x2C,0xA9,0x28,0x39,0xA8,0xEC,0x49,0x83,0x42,0xE3,
0x84,0x0F,0xBB,0x9A,0x6C,0x55,0x61,0xAC,0x82,0x7C,0xA1,0x60,0x2D,0x77,0x4C,0xE9,
0x99,0xB4,0x64,0x3B,0x9A,0x50,0x1C,0x31,0x08,0x24,0x14,0x9F,0xA9,0xE7,0x91,0x2B,
0x18,0xE6,0x3D,0x98,0x63,0x14,0x60,0x58,0x05,0x65,0x9F,0x1D,0x37,0x52,0x87,0xF7,
0xA7,0xEF,0x94,0x02,0xC6,0x1B,0xD3,0xBF,0x55,0x45,0xB3,0x89,0x80,0xBF,0x3A,0xEC,
0x54,0x94,0x4E,0xAE,0xFD,0xA7,0x7A,0x6D,0x74,0x4E,0xAF,0x18,0xCC,0x96,0x09,0x28,
0x21,0x00,0x57,0x90,0x60,0x69,0x37,0xBB,0x4B,0x12,0x07,0x3C,0x56,0xFF,0x5B,0xFB,
0xA4,0x66,0x0A,0x08,0xA6,0xD2,0x81,0x56,0x57,0xEF,0xB6,0x3B,0x5E,0x16,0x81,0x77,
0x04,0xDA,0xF6,0xBE,0xAE,0x80,0x95,0xFE,0xB0,0xCD,0x7F,0xD6,0xA7,0x1A,0x72,0x5C,
0x3C,0xCA,0xBC,0xF0,0x08,0xA3,0x22,0x30,0xB3,0x06,0x85,0xC9,0xB3,0x20,0x77,0x13,
0x85,0xDF,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xA8,0x30,0x81,0xA5,0x30,0x81,0xA2,
0x06,0x03,0x55,0x1D,0x01,0x04,0x81,0x9A,0x30,0x81,0x97,0x80,0x10,0x5B,0xD0,0x70,
0xEF,0x69,0x72,0x9E,0x23,0x51,0x7E,0x14,0xB2,0x4D,0x8E,0xFF,0xCB,0xA1,0x72,0x30,
0x70,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x0B,0x13,0x22,0x43,0x6F,0x70,0x79,
0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x37,0x20,0x4D,
0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x1E,
0x30,0x1C,0x06,0x03,0x55,0x04,0x0B,0x13,0x15,0x4D,0x69,0x63,0x72,0x6F,0x73,0x6F,
0x66,0x74,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x21,
0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x13,0x18,0x4D,0x69,0x63,0x72,0x6F,0x73,0x6F,
0x66,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,
0x79,0x82,0x0F,0x00,0xC1,0x00,0x8B,0x3C,0x3C,0x88,0x11,0xD1,0x3E,0xF6,0x63,0xEC,
0xDF,0x40,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,
0x00,0x03,0x82,0x01,0x01,0x00,0x95,0xE8,0x0B,0xC0,0x8D,0xF3,0x97,0x18,0x35,0xED,
0xB8,0x01,0x24,0xD8,0x77,0x11,0xF3,0x5C,0x60,0x32,0x9F,0x9E,0x0B,0xCB,0x3E,0x05,
0x91,0x88,0x8F,0xC9,0x3A,0xE6,0x21,0xF2,0xF0,0x57,0x93,0x2C,0xB5,0xA0,0x47,0xC8,
0x62,0xEF,0xFC,0xD7,0xCC,0x3B,0x3B,0x5A,0xA9,0x36,0x54,0x69,0xFE,0x24,0x6D,0x3F,
0xC9,0xCC,0xAA,0xDE,0x05,0x7C,0xDD,0x31,0x8D,0x3D,0x9F,0x10,0x70,0x6A,0xBB,0xFE,
0x12,0x4F,0x18,0x69,0xC0,0xFC,0xD0,0x43,0xE3,0x11,0x5A,0x20,0x4F,0xEA,0x62,0x7B,
0xAF,0xAA,0x19,0xC8,0x2B,0x37,0x25,0x2D,0xBE,0x65,0xA1,0x12,0x8A,0x25,0x0F,0x63,
0xA3,0xF7,0x54,0x1C,0xF9,0x21,0xC9,0xD6,0x15,0xF3,0x52,0xAC,0x6E,0x43,0x32,0x07,
0xFD,0x82,0x17,0xF8,0xE5,0x67,0x6C,0x0D,0x51,0xF6,0xBD,0xF1,0x52,0xC7,0xBD,0xE7,
0xC4,0x30,0xFC,0x20,0x31,0x09,0x88,0x1D,0x95,0x29,0x1A,0x4D,0xD5,0x1D,0x02,0xA5,
0xF1,0x80,0xE0,0x03,0xB4,0x5B,0xF4,0xB1,0xDD,0xC8,0x57,0xEE,0x65,0x49,0xC7,0x52,
0x54,0xB6,0xB4,0x03,0x28,0x12,0xFF,0x90,0xD6,0xF0,0x08,0x8F,0x7E,0xB8,0x97,0xC5,
0xAB,0x37,0x2C,0xE4,0x7A,0xE4,0xA8,0x77,0xE3,0x76,0xA0,0x00,0xD0,0x6A,0x3F,0xC1,
0xD2,0x36,0x8A,0xE0,0x41,0x12,0xA8,0x35,0x6A,0x1B,0x6A,0xDB,0x35,0xE1,0xD4,0x1C,
0x04,0xE4,0xA8,0x45,0x04,0xC8,0x5A,0x33,0x38,0x6E,0x4D,0x1C,0x0D,0x62,0xB7,0x0A,
0xA2,0x8C,0xD3,0xD5,0x54,0x3F,0x46,0xCD,0x1C,0x55,0xA6,0x70,0xDB,0x12,0x3A,0x87,
0x93,0x75,0x9F,0xA7,0xD2,0xA0,
	};
	DWORD err;
	PCCERT_CONTEXT pRootCert = CertCreateCertificateContext(X509_ASN_ENCODING, RootCertEncoded, sizeof(RootCertEncoded));
	if (pRootCert == NULL) {
		err = GetLastError();
		goto Done;
	}
	if (!CryptAcquireContext(&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
		err = GetLastError();
		goto Done;
	}
	CRYPT_DATA_BLOB CertStoreBlob;
	CertStoreBlob.cbData = cbCertChain;
	CertStoreBlob.pbData = (BYTE*)lpCertChain;
	HCERTSTORE hCertStore = CertOpenStore(
		CERT_STORE_PROV_PKCS7,
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		hProv,
		CERT_STORE_NO_CRYPT_RELEASE_FLAG,
		&CertStoreBlob);
	if (hCertStore == NULL) {
		err = GetLastError();
		goto Done;
	}
	PCCERT_CONTEXT pFirstCert = CertEnumCertificatesInStore(hCertStore, NULL);
	if (pFirstCert == NULL) {
		err = GetLastError();
		goto Done;
	}
	err = WPAValidateCertChain(hCertStore, pFirstCert, RootCertEncoded, sizeof(RootCertEncoded));
	if (err != ERROR_SUCCESS) {
		goto Done;
	}
	if (!CryptCreateHash(hProv, CALG_MD5, NULL, 0, &hHash)) {
		err = GetLastError();
		goto Done;
	}
	if (!CryptHashData(hHash, (CONST BYTE*)pbData, cbData, 0)) {
		err = GetLastError();
		goto Done;
	}
	if (!CryptImportPublicKeyInfoEx(hProv, X509_ASN_ENCODING, &pFirstCert->pCertInfo->SubjectPublicKeyInfo, CALG_RSA_SIGN, 0, NULL, &hKey)) {
		err = GetLastError();
		goto Done;
	}
	if (!CryptVerifySignature(hHash, pbSignature, cbSignature, hKey, NULL, 0)) {
		err = GetLastError();
		goto Done;
	}
Done:
	if (hHash != NULL) {
		CryptDestroyHash(hHash);
	}
	if (hKey != NULL) {
		CryptDestroyKey(hKey);
	}
	if (pRootCert != NULL) {
		CertFreeCertificateContext(pRootCert);
	}
	if (hProv != NULL) {
		CryptReleaseContext(hProv, 0);
	}
	return err;
}

__forceinline LONG sub_104DF79(LPCSTR szHaystack, ULONG nHaystackOffset, DWORD cchHaystack, LPCSTR szNeedle, DWORD cchNeedle) {
	for (ULONG nOffset = nHaystackOffset; (LONG)(nOffset - nHaystackOffset) <= (LONG)(cchHaystack - cchNeedle); nOffset++) {
		if (!_strnicmp(szHaystack + nOffset, szNeedle, cchNeedle)) {
			return nOffset;
		}
	}
	return -1;
}

PCSTR sub_104E032(PCSTR arg_0, PDWORD arg_4) {
	if (*arg_0 == ',') {
		*arg_4 = 0;
		return arg_0;
	}
	PCSTR esi = arg_0;
	while (*esi && *esi != ',') {
		esi++;
	}
	if (sscanf(arg_0, "%x", arg_4) == 0) {
		*arg_4 = 0;
	}
	return esi;
}

ULONG sub_104E12B(LPCSTR lpString, LPSTR lpString1, DWORD iMaxLength, LPSTR arg_C, DWORD arg_10) {
	DWORD edi = lstrlenA(lpString);
	DWORD var_4 = 0;
	ULONG eax;
	for (;;) {
		eax = sub_104DF79(arg_C, var_4, arg_10 - var_4, lpString, edi);
		if ((LONG)eax < 0) {
			return 0;
		}
		if (arg_C[eax+edi] == ' ' || arg_C[eax+edi] == '=') {
			break;
		}
		var_4 = edi + eax;
	}
	eax += edi;
	while (arg_C[eax] != '=') {
		if (arg_C[eax] == '\n' || arg_C[eax] == '\r' || eax >= arg_10) {
			return 0;
		}
		++eax;
	}
	++eax;
	while (eax < arg_10 && arg_C[eax] == ' ') {
		++eax;
	}
	PCSTR edx = &arg_C[eax];
	while (eax < arg_10 && arg_C[eax] != '\n' && arg_C[eax] != '\r') {
		++eax;
	}
	while (eax > var_4 && arg_C[eax-1] == ' ') {
		--eax;
	}
	arg_C[eax] = 0;
	lstrcpynA(lpString1, edx, iMaxLength);
	return lstrlenA(lpString1);
}

void sub_104E349(LPCVOID lpData, DWORD cbData, BYTE md5[16]) {
	MD5_CTX ctx;
	MD5Init(&ctx);
	MD5Update(&ctx, (CONST BYTE*)lpData, cbData);
	MD5Final(&ctx);
	memcpy(md5, ctx.digest, MD5_LEN);
}

//#include "bios.inl"

bool sub_104E5E8(LPSTR arg_0, DWORD arg_4, LPCWSTR lpFileName) {
	char Src[MAX_PATH];
	char Dest[32];
	if (!sub_104E12B("HashBlocks", Src, MAX_PATH, arg_0, arg_4)) {
		return false;
	}
	DWORD var_24 = 0;
	sscanf(Src, "%d", &var_24);
	if (var_24 == 0) {
		return false;
	}
	if (!sub_104E12B("HashSize", Src, MAX_PATH, arg_0, arg_4)) {
		return false;
	}
	DWORD dwNumberOfBytesToMap = 0;
	sscanf(Src, "%d", &dwNumberOfBytesToMap);
	if (dwNumberOfBytesToMap == 0) {
		return false;
	}
	DWORD esi = GetTickCount() % var_24;
	sprintf(Dest, "Hash%03d", esi);
	if (!sub_104E12B(Dest, Src, MAX_PATH, arg_0, arg_4)) {
		return false;
	}
	DWORD var_58[4];
	if (sscanf(Src, "%08x,%08x,%08x,%08x", &var_58[0], &var_58[1], &var_58[2], &var_58[3]) != 4) {
		return false;
	}
	AutoFileHandle hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		return false;
	}
	AutoFileMappingHandle hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
	if (hFileMapping == NULL) {
		return false;
	}
	esi *= dwNumberOfBytesToMap;
	AutoMapViewPtr<BYTE> pMapView = (BYTE*)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, esi, dwNumberOfBytesToMap);
	if (pMapView == NULL) {
		return false;
	}
	BYTE md5[16];
	BYTE var_20[] = {0x98, 0xAB, 0x00, 0xE0, 0x5F, 0x2B, 0x12, 0x97, 0xF4, 0xD3, 0x3F, 0x29, 0x78, 0x23, 0x90, 0x4A};
	sub_104E349(pMapView, dwNumberOfBytesToMap, md5);
	WPADecrypt((LPBYTE)var_58, sizeof(var_58), var_20);
	if (memcmp(md5, var_58, sizeof(md5))) {
		return false;
	}
	return true;
}

bool __forceinline WPAFindMarkerInBIOS(LPCSTR var_78, BYTE* arg_4, DWORD arg_8) {
			WCHAR var_9D0[MAX_PATH];
			lstrcpy(var_9D0, CWPAStringsDecryptor(word_10759C4, sizeof(word_10759C4)/sizeof(word_10759C4[0]), unk_1019768));
			CWPAStringsDecryptor var_3B8(word_10759B4, sizeof(word_10759B4)/sizeof(word_10759B4[0]), unk_1019768);
			for (LONG var_14 = -1; var_14 < 100; var_14++) {
				WCHAR var_BD8[MAX_PATH];
				wsprintf(var_BD8, var_9D0, var_14);
				char Dest[MAX_PATH];
				wcstombs(Dest, var_14 == -1 ? (LPCWSTR)var_3B8 : var_BD8, MAX_PATH);
				Dest[MAX_PATH - 1] = 0;
				char var_5C0[MAX_PATH];
				if (!sub_104E12B(Dest, var_5C0, MAX_PATH, (LPSTR)arg_4, arg_8)) {
					return false;
				}
				DWORD var_2C = 0;
				DWORD var_10 = 0;
				DWORD _arg_0 = 0;
				const char* p = sub_104E032(var_5C0, &var_2C);
				if (*p) {
					++p;
					if (*p) {
						p = sub_104E032(p, &var_10);
						if (*p) {
							++p;
							if (*p) {
								p = sub_104E032(p, &_arg_0);
								if (*p) {
									++p;
								}
							}
						}
					}
				}
				const char* esi = p;
				for (; *esi; esi++)
					if (*esi != ' ')
						break;
				if (var_2C * 0x10 + var_10 < 0xE0000 || var_2C * 0x10 + var_10 >= 0x100000) {
					return false;
				}
				var_10 += (var_2C - 0xE000) * 0x10;
				if (_arg_0 == 0) {
					_arg_0 = MAX_PATH;
				}
				DWORD var_18 = 0x20000 - var_10;
				_arg_0 = *(*&var_18 < *&_arg_0 ? &var_18 : &_arg_0);
				if (!*esi || lstrlenA(esi) == 0) {
					return false;
				}
				DWORD edi = lstrlenA(esi);
				if (_arg_0 < edi || edi < 5) {
					continue;
				}
				LONG _esi = sub_104DF79(var_78, var_10, _arg_0, esi, edi);
				if (_esi != -1) {
					return true;
				}
			}
			return false;
}

bool ParseOEMBIOSFile(WPAFILETYPE FileType, BYTE* arg_4, DWORD arg_8) {
	AutoSectionViewPtr<void> var_3C;
	SIZE_T dwSectionSize;
	LARGE_INTEGER SectionOffset;
	UNICODE_STRING DestinationString;
	OBJECT_ATTRIBUTES ObjectAttributes;
	WCHAR String1[MAX_PATH];
	if (FileType == WPAFileType0) {
		bool fSetupFailed;
		do {
		// L"\\Device\\PhysicalMemory"
		WCHAR var_70[] = {0xB339,0x8C7D,0x2C74,0xCEE9,0xB39C,0x1DB0,0x4C65,0x540B,0xDFF7,0x0C67,0xF117,0xD8DC,0x5C18,0xD8CD,0xE863,0x9B1B,0x65EF,0xD1D6,0x20D5,0x6E86,0xE5E3,0x8786,0xFD88,0x9195,0xFFD0};
		lstrcpy(String1, CWPAStringsDecryptor(var_70, sizeof(var_70)/sizeof(var_70[0]), unk_1019768));
		RtlInitUnicodeString(&DestinationString, String1);
		ObjectAttributes.Length = sizeof(ObjectAttributes);
		ObjectAttributes.RootDirectory = NULL;
		ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
		ObjectAttributes.ObjectName = &DestinationString;
		ObjectAttributes.SecurityDescriptor = NULL;
		ObjectAttributes.SecurityQualityOfService = NULL;
		AutoNtHandle var_24;
		NTSTATUS ntstatus = NtOpenSection(&var_24, SECTION_MAP_READ, &ObjectAttributes);
		ZeroMemory(String1, sizeof(String1));
		if (!NT_SUCCESS(ntstatus)) {
			fSetupFailed = true;
			break;
		}
		dwSectionSize = 0x20000;
		SectionOffset.QuadPart = 0xE0000;
		ntstatus = NtMapViewOfSection(var_24, NtCurrentProcess(), &var_3C, 0, dwSectionSize, &SectionOffset, &dwSectionSize, ViewShare, 0, PAGE_READONLY);
		if (!NT_SUCCESS(ntstatus)) {
			fSetupFailed = true;
			break;
		}
		fSetupFailed = false;
		} while (0);
		if (fSetupFailed) {
			return false;
		}
	}
	char String[MAX_PATH] = {0};
	sub_104E12B("Type", String, MAX_PATH, (LPSTR)arg_4, arg_8);
	if (lstrlenA(String) == 0 || !lstrcmpiA(String, "oem")) {
		if (FileType == WPAFileType0 && WPAFindMarkerInBIOS((LPCSTR)(void*)var_3C, arg_4, arg_8)) {
			return true;
		}
	} else if (!lstrcmpiA(String, "volume")) {
		if (FileType == WPAFileType1) {
			return true;
		}
		goto x;
	} else if (!lstrcmpiA(String, "retail")) {
		if (FileType == WPAFileType2) {
			return true;
		}
		x:;
	}
	return false;
}

static DWORD __forceinline func1(CONST BYTE* p) {
	DWORD tmp = *(DWORD*)p;
	return *(DWORD*)(p + tmp + 4);
}
static __forceinline CONST BYTE* func2(CONST BYTE* p) {
	DWORD tmp = *(DWORD*)p;
	return p + tmp + 8;
}
static DWORD __forceinline func3(CONST BYTE* p) {
	return *(DWORD*)p;
}
static __forceinline CONST BYTE* func4(CONST BYTE* p) {
	return p + 4;
}

extern "C" bool sub_104F0CA(WPAFILETYPE FileType, LPCWSTR lpszBaseDir, LPCWSTR arg_8, INT arg_C, PDWORD arg_10, BLPIDFILE_VERSIONINFO* arg_14) {
	if (FileType != WPAFileType0 && FileType != WPAFileType1 && FileType != WPAFileType2 && FileType != WPAFileType3) {
		return false;
	}
	WCHAR Buffer[MAX_PATH];
	WCHAR Dest[MAX_PATH];
	WCHAR FileName[MAX_PATH];
	WCHAR var_B38[MAX_PATH];
	// L"%s\\SECUPD.DAT"
	WCHAR var_74[] = {0x83EA,0xF353,0xD2B3,0xD92D,0xB95D,0x21E1,0x4D45,0x09AC,0x4E13,0x126F,0x8AEC,0x8E44,0x2F36,0x7DD7,0xAE13,0xF5C4};
	// L"%s\\SECUPD.SIG"
	WCHAR var_54[] = {0x83EA,0xF353,0xD2B3,0xD92D,0xB95D,0x21E1,0x5D45,0xD545,0xB06C,0x2352,0xC31D,0x11DB,0x7F1C,0x8D1F,0x0B71,0xE130};
	// L"%s\\OEMBIOS.DAT"
	WCHAR var_98[] = {0x907C,0x71D7,0xD07B,0x4699,0x07EC,0xC954,0xA6EC,0x941D,0x033F,0x7877,0x485B,0xF286,0xE2A6,0x34CB,0x1D06,0x4A0E,0xD307};
	// L"%s\\OEMBIOS.SIG"
	WCHAR var_BC[] = {0x907C,0x71D7,0xD07B,0x4699,0x07EC,0xC954,0xA6EC,0x721D,0x2BF8,0x0533,0xFB59,0x6C48,0xB771,0x8DD2,0xD5FF,0x5D46,0xB451};
	Dest[MAX_PATH - 1] = 0;
	FileName[MAX_PATH - 1] = 0;
	var_B38[MAX_PATH - 1] = 0;
	if (!GetSystemDirectory(Buffer, MAX_PATH)) {
		return false;
	}
	if (FileType == WPAFileType0 || FileType == WPAFileType1 || FileType == WPAFileType2) {
		_snwprintf(Dest, MAX_PATH - 1, CWPAStringsDecryptor(var_98, sizeof(var_98)/sizeof(var_98[0]), unk_1019768), Buffer);
		_snwprintf(FileName, MAX_PATH - 1, CWPAStringsDecryptor(var_BC, sizeof(var_BC)/sizeof(var_BC[0]), unk_1019768), Buffer);
		_snwprintf(var_B38, MAX_PATH - 1, L"%s\\oembios.bin", Buffer);
	} else {
		if (lpszBaseDir != NULL) {
			_snwprintf(Dest, MAX_PATH - 1, CWPAStringsDecryptor(var_74, sizeof(var_74)/sizeof(var_74[0]), unk_1019768), lpszBaseDir);
			_snwprintf(FileName, MAX_PATH - 1, CWPAStringsDecryptor(var_54, sizeof(var_54)/sizeof(var_54[0]), unk_1019768), lpszBaseDir);
		} else {
			_snwprintf(Dest, MAX_PATH - 1, CWPAStringsDecryptor(var_74, sizeof(var_74)/sizeof(var_74[0]), unk_1019768), Buffer);
			_snwprintf(FileName, MAX_PATH - 1, CWPAStringsDecryptor(var_54, sizeof(var_54)/sizeof(var_54[0]), unk_1019768), Buffer);
		}
	}
	AutoFileHandle var_D4 = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (var_D4 == INVALID_HANDLE_VALUE) {
		return false;
	}
	DWORD tmp = GetFileSize(var_D4, NULL);
	if (tmp == INVALID_FILE_SIZE) {
		return false;
	}
	AutoFileMappingHandle var_EC = CreateFileMapping(var_D4, NULL, PAGE_READONLY, 0, 0, NULL);
	if (var_EC == NULL) {
		return false;
	}
	AutoMapViewPtr<BYTE> var_20 = (BYTE*)MapViewOfFile(var_EC, FILE_MAP_READ, 0, 0, 0);
	if (var_20 == NULL) {
		return false;
	}
	AutoFileHandle var_C8 = CreateFile(Dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (var_C8 == INVALID_HANDLE_VALUE) {
		return false;
	}
	DWORD var_8 = GetFileSize(var_C8, NULL);
	if (var_8 == INVALID_FILE_SIZE) {
		return false;
	}
	AutoFileMappingHandle var_E0 = CreateFileMapping(var_C8, NULL, PAGE_READONLY, 0, 0, NULL);
	if (var_E0 == NULL) {
		return false;
	}
	AutoMapViewPtr<BYTE> var_34 = (BYTE*)MapViewOfFile(var_E0, FILE_MAP_READ, 0, 0, 0);
	if (var_34 == NULL) {
		return false;
	}
	DWORD err = sub_104C095(var_34, var_8, func4(var_20), func3(var_20), func2(var_20), func1(var_20));
	if (err != 0) {
		return false;
	}
	AutoHeapPtr<BYTE> var_14 = (BYTE*)HeapAlloc(GetProcessHeap(), 0, var_8);
	if (var_14 == NULL) {
		return false;
	}
	memcpy(var_14, var_34, var_8);
	CWPACryptHelper var_100;
	static const BYTE byte_1019880[] = {0x00,0x19,0x4C,0x5E,0xF2,0xB7,0x10,0x79,0x4D,0x53,0x14,0x3B,0xED,0xB1,0x7F,0x58,0x1B,0xEA,0x4C,0xC5,0x0E,0x04,0x90,0x56,0x3D,0x32,0xE9,0x67,0xDB,0x60,0x97,0xED,0xB1,0x5A,0x1B,0x15,0x0F,0x84,0xBA,0x02,0xE2,0xB7,0x6E,0x64,0x7F,0xF9,0xB7,0xBC,0x6A,0x07,0x94,0x92,0xC3,0x32,0xC8,0x96,0x35,0x59,0x07,0x71,0xD8,0x60,0x37,0xBE,0x6D,0x86,0x21,0xF9,0xCB,0xAC,0xF6,0x65,0xDD,0x9E,0x5D,0xBE,0x6E,0x4B,0x6C,0xB7,0x1A,0x70,0x14,0x84,0x06,0x0A,0x44,0x84,0x67,0xC0,0xED,0x51,0x6D,0xC8,0x9E,0x7F,0x2A,0x48,0x38,0xA6,0x64,0x6D,0xF5,0xEC,0xA9,0x92,0xF6,0x2A,0xD7};
	static const BYTE byte_1019880_copy[] = {0x00,0x19,0x4C,0x5E,0xF2,0xB7,0x10,0x79,0x4D,0x53,0x14,0x3B,0xED,0xB1,0x7F,0x58,0x1B,0xEA,0x4C,0xC5,0x0E,0x04,0x90,0x56,0x3D,0x32,0xE9,0x67,0xDB,0x60,0x97,0xED,0xB1,0x5A,0x1B,0x15,0x0F,0x84,0xBA,0x02,0xE2,0xB7,0x6E,0x64,0x7F,0xF9,0xB7,0xBC,0x6A,0x07,0x94,0x92,0xC3,0x32,0xC8,0x96,0x35,0x59,0x07,0x71,0xD8,0x60,0x37,0xBE,0x6D,0x86,0x21,0xF9,0xCB,0xAC,0xF6,0x65,0xDD,0x9E,0x5D,0xBE,0x6E,0x4B,0x6C,0xB7,0x1A,0x70,0x14,0x84,0x06,0x0A,0x44,0x84,0x67,0xC0,0xED,0x51,0x6D,0xC8,0x9E,0x7F,0x2A,0x48,0x38,0xA6,0x64,0x6D,0xF5,0xEC,0xA9,0x92,0xF6,0x2A,0xD7};
	if (FileType == WPAFileType3) {
		if (FAILED(var_100.sub_104FD06(byte_1019880, sizeof(byte_1019880), 0))) {
			return false;
		}
	} else {
		if (FAILED(var_100.sub_104FD06(byte_1019880_copy, sizeof(byte_1019880_copy), 0))) {
			return false;
		}
	}
	DWORD var_104;
	var_100.sub_1050495(var_14, var_8, &var_104);
	static const BYTE dword_101986C[16] = {0x12, 0x98, 0xEF, 0x6B, 0x12, 0xC5, 0xCC, 0xE4, 0x98, 0x42, 0x71, 0x08, 0x96, 0xEE, 0xD2, 0x3E};
	if (FileType == WPAFileType3) {
		WPADecrypt(var_14, var_8, dword_101986C);
	} else {
		WPADecrypt(var_14, var_8, dword_101986C);
	}
	var_34.take(NULL);
	var_E0.Close();
	var_C8.Close();
	if (FileType == WPAFileType0 || FileType == WPAFileType1 || FileType == WPAFileType2) {
		if (!sub_104E5E8((LPSTR)(BYTE*)var_14, var_8, var_B38)) {
			return false;
		}
		return ParseOEMBIOSFile(FileType, var_14, var_8);
	} else if (FileType == WPAFileType3) {
		if (arg_14 != NULL) {
			return GetBLVersion(var_14, var_8, arg_14) == S_OK;
		}
		if (arg_10 != 0) {
			return SearchAndCheckPID(var_14, var_8, arg_8, arg_C, arg_10) == S_OK;
		}
	}
	return false;
}

//#include "bios_eh.inc"
