micetools/src/micetools/miceboot/mxstartup.c

1147 lines
36 KiB
C
Raw Normal View History

2022-10-30 17:33:02 +00:00
#include <Windows.h>
#include <shellapi.h>
2023-07-16 21:13:34 +00:00
#include <shlwapi.h>
2022-10-30 17:33:02 +00:00
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
2023-07-16 21:13:34 +00:00
#include <string.h>
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
#include "../amBackupStructs.h"
#include "../lib/am/amBackup.h"
#include "../lib/am/amEeprom.h"
#include "../lib/am/amLog.h"
#include "../lib/am/amPlatform.h"
#include "../lib/ami/amiCrc.h"
#include "../lib/ami/amiDebug.h"
2022-10-30 17:33:02 +00:00
#include "ewfapi.h"
2023-07-16 21:13:34 +00:00
#include "osg.h"
#include "osu.h"
2022-10-30 17:33:02 +00:00
typedef enum {
MxError_Unknown = -1,
MxError_None = 0,
2023-07-16 21:13:34 +00:00
MxError_SecurityCheck = 500,
2022-10-30 17:33:02 +00:00
MxError_Ewf = 501,
MxError_Version = 502,
MxError_NoKeyFile = 503,
MxError_DiskAccessPrivilege = 504,
MxError_SystemMount = 505,
2023-07-16 21:13:34 +00:00
MxError_MountUpdate = 506,
2022-10-30 17:33:02 +00:00
MxError_MxMaster = 507,
2023-07-16 21:13:34 +00:00
MxError_OSUpdateKeyFile = 508,
MxError_ExecuteOSUpdate = 509,
MxError_EWFEnable = 510,
2022-10-30 17:33:02 +00:00
MxError_SBR = 511,
MxError_SysKeyDelete = 512,
2023-07-16 21:13:34 +00:00
MxError_MountDriver = 513,
MxError_RingRegistry = 514,
MxError_UnMountVolume = 540,
MxError_MountRecovery = 541,
MxError_ChangeActivePartition = 543,
MxError_Reboot = 545,
MxError_GetCD = 546,
2022-10-30 17:33:02 +00:00
} MxError_t;
typedef enum {
Init = 0,
CheckEwf = 1,
EwfDisabled = 2,
GetSBR = 3,
NormalBoot = 4,
SystemUpdate2 = 5,
SystemUpdate3 = 6,
Done = 7,
} StartupStep_t;
#define VERSION_BUFFER 256
#define VERSION_FILE "C:\\System\\SystemVersion.txt"
#define DEFAULT_VERSION_FILE "C:\\System\\DefaultSystemVersion.txt"
#define SYSTEM_KEY_FILE "Z:\\SystemKeyFile"
#define OS_UPDATE_KEY_FILE "Z:\\UpdateKeyFile"
#define SYSTEM_VOLUME "C:\\System\\Execute\\System"
2023-07-16 21:13:34 +00:00
#define DEFAULT_DRIVERS "Z:\\Minint\\System32\\DEFAULT_DRIVERS"
2022-10-30 17:33:02 +00:00
#define SYSTEM_MOUNT "S:"
2023-07-16 21:13:34 +00:00
#define UPDATE_MOUNT "W:"
#define UPDATE_MOUNT_SLASH "W:\\"
#define DRIVERS_MOUNT "V:"
#define DRIVERS_MOUNT_SLASH "V:\\"
#define OS_UPDATE_CONF "W:\\OSupdate2.conf"
#define DRIVERS_UPDATE_EXE "V:\\MXOSUpdate.exe"
#define UPDATE_EXE "W:\\MXOSUpdate.exe"
2022-10-30 17:33:02 +00:00
#define NEXT_HOP_CWD SYSTEM_MOUNT "\\"
#define NEXT_HOP_MXMASTER NEXT_HOP_CWD "mxmaster.exe"
#define CACLS_REMPERM_EXECUTE "cacls c:\\system\\execute /t /e /p AppUser:N"
#define CACLS_REMPERM_Z "cacls z:\\ /t /e /p appuser:N"
#define CACLS_REMPERM_S "cacls s:\\ /t /e /p appuser:N"
2023-07-16 21:13:34 +00:00
#define TRUECRYPT "TrueCrypt"
2022-10-30 17:33:02 +00:00
// Rather than implement these sums in code, we're just going to use the
// presummed versions, because we have nothing to gain by obfuscating this.
// These two sum to TC_PASSWORD
#define TC_PASSWORD_1 "3d550a335d2557055d2b3d1444153348"
#define TC_PASSWORD_2 "36105d2e0b3c1b5f1336365f335a3f1c"
#define TC_PASSWORD "segahardpassword"
// These two sum to SYSTEM_KEYFILE_ADS
#define SYSTEM_KEYFILE_1 "041443255b204a3f054d1b4c352a22292f211b29440e1237591f2e49375d093967614d"
#define SYSTEM_KEYFILE_2 "3f26192e1e532a26680f2a2c3039534b363b2923082c41421a5537241408700d020b18"
#define SYSTEM_KEYFILE_ADS "C:\\System\\Execute\\DLL:SystemKeyFile"
// These two sum to OS_UPDATE_ADS
#define OS_UPDATE_KEYFILE_1 "4019582c56283006300b40042110143d603b3d3b1d012b5c0d5423152235163f624a43"
#define OS_UPDATE_KEYFILE_2 "03210427234b445f3d51057444536137052107112f392a14570d515029306307072222"
#define OS_UPDATE_KEYFILE_ADS "C:\\System\\Execute\\DLL:UpdateKeyFile"
int LOG_EN_PLATFORM = 0;
void log(char* function, unsigned int line_number, char* fmt, ...) {
va_list args;
va_start(args, fmt);
printf("%s: Line%d ", function, line_number);
vprintf(fmt, args);
va_end(args);
}
2023-07-16 21:13:34 +00:00
BOOL isDebugEnabled(void) {
WIN32_FIND_DATAA find;
HANDLE hFind;
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
hFind = FindFirstFileA(".\\DebugEnable", &find);
if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
return TRUE;
}
FindClose(hFind);
return FALSE;
}
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
colour GetBGColour(void) {
HKEY hkResult;
LSTATUS status;
status =
RegOpenKeyExA(HKEY_USERS, ".Default\\Control Panel\\Colors", 0, KEY_ALL_ACCESS, &hkResult);
if (status != ERROR_SUCCESS) return White;
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
BYTE data[16];
DWORD cbData = sizeof data;
status = RegQueryValueExA(hkResult, "BackGround", NULL, NULL, data, &cbData);
if (status == ERROR_SUCCESS) {
RegCloseKey(hkResult);
return (memcmp(data, "100 100 100", 13) == 0) ? Grey : White;
2022-10-30 17:33:02 +00:00
} else {
2023-07-16 21:13:34 +00:00
RegCloseKey(hkResult);
return White;
2022-10-30 17:33:02 +00:00
}
2023-07-16 21:13:34 +00:00
}
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
OSU_TOP g_Top;
OSU_BOTTOM g_Bottom;
OSU g_Osu;
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
#define LINE5_LEN 32
bool InitGraphics(HINSTANCE hInstance, int nShowCmd) {
g_Top.show_top = 0;
g_Top.debugEnable = isDebugEnabled();
g_Top.top_text_colour = White;
g_Top.top_text_font = 2;
g_Top.str1 = "SYSTEM UPDATE";
g_Bottom.backgroundColour = GetBGColour();
colour bg_invert = g_Bottom.backgroundColour == White ? Black : White;
g_Bottom.line5_colour = bg_invert;
g_Bottom.power_colour = bg_invert;
g_Bottom.status_colour = bg_invert;
g_Bottom.status_font = 2;
g_Bottom.status_str = "NOW LOADING";
g_Bottom.status_use_counter = 1;
g_Bottom.str2 = "";
static char line5[LINE5_LEN];
line5[0] = '\0';
g_Bottom.line5 = line5;
g_Bottom.hide_power = 0;
g_Bottom.power_font = 0;
g_Osu.hInstance = hInstance;
g_Osu.nShowCmd = nShowCmd;
g_Osu.s1 = &g_Top;
g_Osu.s2 = &g_Bottom;
BOOL ret = osgInitDraw(&g_Osu);
if (!ret) amiDebugLog("Error : osgInitDraw error");
return ret != 0;
}
void AppendAsterisk(void) {
EnterCriticalSection(&g_Top.criticalSection);
strcat_s(g_Bottom.line5, LINE5_LEN, "*");
LeaveCriticalSection(&g_Top.criticalSection);
}
void setStrForStep2(void) {
EnterCriticalSection(&g_Top.criticalSection);
// TODO: Wtf was this line?
// FUN_00402c40((basic_string<char,struct_std::char_traits<char>,class_std::allocator<char>_>
// *)
// &g_Bottom.line5);
g_Top.show_top = 1;
g_Top.str2 = "STEP 2";
g_Bottom.status_font = 0;
g_Bottom.status_str = "";
g_Bottom.status_use_counter = 0;
g_Bottom.str2 = "DO NOT TURN OFF THE POWER.";
g_Bottom.hide_power = 1;
g_Bottom.power_font = 0;
LeaveCriticalSection(&g_Top.criticalSection);
}
void setStrForStep3(void) {
EnterCriticalSection(&g_Top.criticalSection);
// TODO: Wtf was this line?
// FUN_00402c40((basic_string<char,struct_std::char_traits<char>,class_std::allocator<char>_>
// *)
// &g_Bottom.line5);
g_Top.show_top = 1;
g_Top.str2 = "STEP 3";
g_Bottom.status_font = 0;
g_Bottom.status_str = "";
g_Bottom.status_use_counter = 0;
g_Bottom.str2 = "DO NOT TURN OFF THE POWER.";
g_Bottom.hide_power = 1;
g_Bottom.power_font = 0;
LeaveCriticalSection(&g_Top.criticalSection);
2022-10-30 17:33:02 +00:00
}
/* Read a version from a text file */
bool GetVersionText(char* version, char* path) {
char buffer[VERSION_BUFFER];
FILE* file;
memset(buffer, 0, sizeof buffer);
if (fopen_s(&file, path, "r") || file == NULL) {
2023-07-16 21:13:34 +00:00
amiDebugLog("Error : GetVersionText error path = %s", path);
2022-10-30 17:33:02 +00:00
return false;
}
fgets(buffer, sizeof buffer, file);
fclose(file);
strncpy_s(version, VERSION_BUFFER, buffer, VERSION_BUFFER);
return true;
}
/* Get the currently running version of the system */
bool GetCurrentVersion(char* version) { return GetVersionText(version, VERSION_FILE); }
/* Get the default version of the system */
bool GetDefaultVersion(char* version) { return GetVersionText(version, DEFAULT_VERSION_FILE); }
/* Mount the system volume */
bool MountSystemVolume(void) {
char command[256];
2023-07-16 21:13:34 +00:00
snprintf(command, sizeof command, TRUECRYPT " /p %s /k %s /v %s /l %s /w /s /q", TC_PASSWORD,
SYSTEM_KEY_FILE, SYSTEM_VOLUME, SYSTEM_MOUNT);
2022-10-30 17:33:02 +00:00
int ret = osuExecProcess(command);
if (ret == 0) return true;
2023-07-16 21:13:34 +00:00
amiDebugLog("Error : osuExecProcess error. ret = %d", ret);
2022-10-30 17:33:02 +00:00
return false;
2023-07-16 21:13:34 +00:00
}
/* Try to mount the system volume with up to 100 retries (20 seconds) */
2022-10-30 17:33:02 +00:00
bool TryMountSystemVolume(void) {
for (int i = 0; i < 100; i++) {
if (MountSystemVolume()) return true;
Sleep(200);
}
return false;
}
/* Copies the file at src to dst */
2023-07-16 21:13:34 +00:00
bool GetKeyFile(LPCSTR pszSrc, LPCSTR pszDst) {
HANDLE hSrc = CreateFileA(pszSrc, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hSrc == INVALID_HANDLE_VALUE) {
amiDebugLog("Error : CreateFile Src error");
2022-10-30 17:33:02 +00:00
return false;
}
2023-07-16 21:13:34 +00:00
HANDLE hDst =
CreateFileA(pszDst, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDst == INVALID_HANDLE_VALUE) {
CloseHandle(hSrc);
amiDebugLog("Error : CreateFile Dst error");
2022-10-30 17:33:02 +00:00
return false;
}
CHAR readBuffer[260];
2023-07-16 21:13:34 +00:00
DWORD nRead;
if (!ReadFile(hSrc, readBuffer, 255, &nRead, NULL)) {
CloseHandle(hSrc);
CloseHandle(hDst);
amiDebugLog("Error : ReadFile error");
2022-10-30 17:33:02 +00:00
return false;
}
2023-07-16 21:13:34 +00:00
readBuffer[nRead] = '\0';
2022-10-30 17:33:02 +00:00
DWORD written;
2023-07-16 21:13:34 +00:00
bool ret = WriteFile(hDst, readBuffer, strlen(readBuffer), &written, NULL) != 0;
if (!ret) amiDebugLog("Error : WriteFile error");
CloseHandle(hSrc);
CloseHandle(hDst);
2022-10-30 17:33:02 +00:00
return ret;
}
2023-07-16 21:13:34 +00:00
void DeleteMounteDevices(void) {
if (RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SYSTEM\\MountedDevices") != ERROR_SUCCESS)
amiDebugLog("Error : RegDeleteKeyA failed.");
}
2022-10-30 17:33:02 +00:00
bool GetSystemKeyFile() { return GetKeyFile(SYSTEM_KEYFILE_ADS, SYSTEM_KEY_FILE); };
2022-12-24 03:04:04 +00:00
bool GetOSUpdateKeyFile() { return GetKeyFile(OS_UPDATE_KEYFILE_ADS, OS_UPDATE_KEY_FILE); };
2022-10-30 17:33:02 +00:00
bool SetDiskAccessPrivilege() {
int i;
for (i = 0; i < 100; i++) {
if (osuExecProcess(CACLS_REMPERM_EXECUTE) != -140) break;
Sleep(200);
}
if (i == 100) {
2023-07-16 21:13:34 +00:00
amiDebugLog("Error : osuExecProcess error");
2022-10-30 17:33:02 +00:00
return false;
}
for (i = 0; i < 100; i++) {
if (osuExecProcess(CACLS_REMPERM_Z) != -140) break;
Sleep(200);
}
if (i == 100) {
2023-07-16 21:13:34 +00:00
amiDebugLog("Error : osuExecProcess error");
2022-10-30 17:33:02 +00:00
return false;
}
for (i = 0; i < 100; i++) {
if (osuExecProcess(CACLS_REMPERM_S) != -140) break;
Sleep(200);
}
if (i == 100) {
2023-07-16 21:13:34 +00:00
amiDebugLog("Error : osuExecProcess error");
2022-10-30 17:33:02 +00:00
return false;
}
return true;
};
bool ExecuteMxMaster() {
HINSTANCE ret = ShellExecuteA(NULL, NULL, NEXT_HOP_MXMASTER, NULL, NEXT_HOP_CWD, 0);
if ((int)ret < 33) {
2023-07-16 21:13:34 +00:00
amiDebugLog("Error : ShellExecute ret = %d", ret);
2022-10-30 17:33:02 +00:00
return false;
}
return true;
2023-07-16 21:13:34 +00:00
}
BOOL SecurityCheck(void) {
AM_PLATFORM_BOARD_TYPE board_type;
if (amPlatformGetBoardType(&board_type) != AM_PLATFORM_STATUS_OK) {
amiDebugLog("Error : amPlatformGetBoardType error");
return FALSE;
}
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
if (board_type == AM_PLATFORM_BOARD_TYPE_UNKNOWN) {
amiDebugLog("Error : BoardType is unknown.");
return FALSE;
}
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
return TRUE;
}
BOOL UnMountVolume(void) {
CHAR mount[4];
mount[1] = ':';
mount[2] = '\\';
mount[3] = '\0';
for (char i = 'D'; i <= 'Z'; i++) {
mount[0] = i;
DeleteVolumeMountPointA(mount);
}
return TRUE;
}
bool MountRecoveryVolume(DWORD dwDisk) {
char targetPath[256];
sprintf_s(targetPath, sizeof targetPath, "\\device\\harddisk%d\\partition2", dwDisk);
if (osuMountPartition(targetPath, "\\\\.\\Z:\\") != 0) {
amiDebugLog("Error : osuMountPartition error");
return FALSE;
}
return TRUE;
}
BOOL GetSystemDiskNumber(DWORD* disk_number, DWORD* partition_no) {
wchar_t windir_path[128];
UINT UVar1 = GetWindowsDirectoryW(windir_path, _countof(windir_path));
if (UVar1 >= 0x100) return FALSE;
wchar_t* pwVar2 = wcschr(windir_path, L'\\');
if (pwVar2 == NULL) return FALSE;
*pwVar2 = L'\0';
wchar_t c_drive_filename[16];
c_drive_filename[0] = L'\0';
errno_t e;
e = wcscat_s(c_drive_filename, _countof(c_drive_filename), L"\\\\.\\");
if (e < 0) return FALSE;
e = wcscat_s(c_drive_filename, _countof(c_drive_filename), windir_path);
if (e < 0) return FALSE;
HANDLE hCDevice = CreateFileW(c_drive_filename, 0xc0000000, 3, NULL, 3, 0x80, NULL);
if (hCDevice == INVALID_HANDLE_VALUE) {
fprintf(stderr, "CreateFileW Failed.\n");
return FALSE;
}
DWORD dwBytesReturned;
STORAGE_DEVICE_NUMBER device;
BYTE extentsBuffer[0x110];
VOLUME_DISK_EXTENTS* lpExtents = (VOLUME_DISK_EXTENTS*)&extentsBuffer;
BOOL res;
res = DeviceIoControl(hCDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device,
sizeof device, &dwBytesReturned, NULL);
if (!res || device.DeviceType != FILE_DEVICE_DISK) {
CloseHandle(hCDevice);
return FALSE;
}
res = DeviceIoControl(hCDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extentsBuffer,
sizeof extentsBuffer, &dwBytesReturned, NULL);
if (!res || lpExtents->NumberOfDiskExtents > 1) {
CloseHandle(hCDevice);
return FALSE;
}
*disk_number = lpExtents->Extents[0].StartingOffset.LowPart;
*partition_no = device.PartitionNumber;
CloseHandle(hCDevice);
return TRUE;
}
MxError_t MxInitStartup(DWORD* diskNumber) {
AppendAsterisk();
if (!SecurityCheck()) {
amiDebugLog("Error : SecurityCheck error");
return MxError_SecurityCheck;
}
AppendAsterisk();
if (!UnMountVolume()) {
amiDebugLog("Error : Unmount error");
return MxError_UnMountVolume;
}
AppendAsterisk();
DWORD partition_no;
if (!GetSystemDiskNumber(diskNumber, &partition_no)) {
amiDebugLog("Error : GetSystemDiskNumber error");
return MxError_GetCD;
}
AppendAsterisk();
if (!MountRecoveryVolume(*diskNumber)) {
amiDebugLog("Error : MountRecoveryVolume error");
return MxError_MountRecovery;
}
return MxError_None;
}
BOOL CheckEwfState(EWF_STATE* state) {
// TODO: Remove this once mice stubs EWF
// *state = EWF_ENABLED;
*state = EWF_DISABLED;
return TRUE;
PEWF_VOLUME_NAME_ENTRY pProVolList = EwfMgrGetProtectedVolumeList();
if (pProVolList == NULL) {
amiDebugLog("Error : Invalid Parameter pProVoList");
return FALSE;
}
if (EwfMgrVolumeNameListIsEmpty(pProVolList)) {
amiDebugLog("EWF EMPTY");
}
while (!EwfMgrVolumeNameListIsEmpty(pProVolList)) {
WCHAR chDrive = EwfMgrGetDriveLetterFromVolumeName(pProVolList->Name);
amiDebugLog("Doing one... %c", chDrive);
if (chDrive == -1) {
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : EwfMgrGetDriveLetterFromVolumeName error");
return FALSE;
}
if (chDrive != L'C') {
EwfMgrVolumeNameEntryPop(&pProVolList);
continue;
}
HANDLE volHandle = EwfMgrOpenProtected(pProVolList->Name);
if (volHandle == INVALID_HANDLE_VALUE) {
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : EwfMgrOpenProtected error");
return FALSE;
}
PEWF_VOLUME_CONFIG config = EwfMgrGetProtectedVolumeConfig(volHandle);
if (config == NULL) {
EwfMgrVolumeNameListDelete(pProVolList);
EwfMgrClose(volHandle);
amiDebugLog("Error : EwfMgrGetProtectedVolumeConfig error");
return FALSE;
}
*state = config->State;
EwfMgrClose(volHandle);
EwfMgrVolumeNameListDelete(pProVolList);
return TRUE;
}
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : Not Found Volume \"C:\\\"");
return FALSE;
}
void ReadLittleEndian(LPBYTE lpBuffer, DWORD_PTR nBytes, LPDWORD lpdwOut) {
*lpdwOut = 0;
if (nBytes > 0) {
for (DWORD_PTR i = 0; i < nBytes; i++) {
*lpdwOut = *lpdwOut + (lpBuffer[i] << ((i * 8) & 0x1f));
}
}
}
bool CheckSectorCRC(LPBYTE lpSector) {
uint32_t table[256];
DWORD readCrc;
ReadLittleEndian(lpSector, 4, &readCrc);
amiCrc32RCreateTable(table);
return amiCrc32RGet(table, 508, &(lpSector[4]), 0) == readCrc;
}
bool GetSBRSlotOSState(DWORD diskNumber, int* updateState) {
BYTE buffer[512];
HANDLE hDisk;
DWORD dwLBA;
if (osuOpenDevice(diskNumber, &hDisk) != 0) return 0;
if (osuReadSector(hDisk, 0, 1, buffer) != 0) {
CloseHandle(hDisk);
return 0;
}
if (buffer[510] != 0x55 || buffer[511] != 0xaa) {
CloseHandle(hDisk);
return 0;
}
if (buffer[482] == 5 || buffer[482] == 15) {
ReadLittleEndian(&(buffer[0x1e6]), 4, &dwLBA);
} else {
if (buffer[498] != 5 && buffer[498] != 15) {
CloseHandle(hDisk);
return 0;
}
ReadLittleEndian(&(buffer[0x1f6]), 4, &dwLBA);
}
if (osuReadSector(hDisk, dwLBA + 3, 1, buffer) != 0) {
CloseHandle(hDisk);
return 0;
}
if (!CheckSectorCRC(buffer)) {
if (osuReadSector(hDisk, dwLBA + 2, 1, buffer) != 0) {
CloseHandle(hDisk);
return 0;
}
if (!CheckSectorCRC(buffer)) {
CloseHandle(hDisk);
return 0;
}
}
*updateState = (unsigned int)(buffer[67]);
CloseHandle(hDisk);
return 1;
}
void SetDefaultShell(void) {
HKEY hkWinlogon;
LSTATUS pProVolList = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
0, KEY_ALL_ACCESS, &hkWinlogon);
if (pProVolList != ERROR_SUCCESS) {
amiDebugLog("Error : RegOpenKeyExA failed.");
} else {
pProVolList = RegSetValueExA(hkWinlogon, "shell", 0, REG_SZ, (LPBYTE) "explorer.exe",
strlen("explorer.exe"));
if (pProVolList != ERROR_SUCCESS) {
amiDebugLog("Error : RegSetValueExA failed.");
}
RegCloseKey(hkWinlogon);
}
}
BOOL RetryCommand(LPSTR lpszCommand, DWORD dwCount, DWORD dwDelay) {
for (DWORD i = 0; i < dwCount; i++) {
if (osuExecProcess(lpszCommand) == 0) return TRUE;
Sleep(dwDelay);
}
return FALSE;
}
BOOL GetSlotDiskNumber(DWORD nDevice, short* pPartition, BYTE slotType) {
BYTE readBuf[512];
BOOL local_10 = FALSE;
HANDLE hDevice;
if (osuOpenDevice(nDevice, &hDevice) != 0) {
amiDebugLog("Error : osuOpenDevice error");
return FALSE;
}
if (osuReadSector(hDevice, 0, 1, readBuf) != 0) {
amiDebugLog("Error : osuReadSector(MBR) error");
CloseHandle(hDevice);
return FALSE;
}
if (readBuf[510] != 0x55 || readBuf[511] != 0xaa) {
amiDebugLog("Error : Partition Table is not found.");
CloseHandle(hDevice);
return FALSE;
}
DWORD extLba;
if (readBuf[482] == 5 || readBuf[482] == 0xf) {
ReadLittleEndian(&(readBuf[0x1e6]), 4, &extLba);
if (readBuf[498] == 0) {
*pPartition = 3;
} else {
*pPartition = 4;
}
} else {
if (readBuf[498] != 5 && readBuf[498] != 0xf) {
amiDebugLog("Error : Invalid Partition Table error");
CloseHandle(hDevice);
return FALSE;
}
ReadLittleEndian(&(readBuf[0x1f6]), 4, &extLba);
*pPartition = 4;
}
if (osuReadSector(hDevice, extLba + 1, 1, readBuf) != 0) {
amiDebugLog("Error : osuReadSector(SPD) error");
CloseHandle(hDevice);
return FALSE;
}
if (!CheckSectorCRC(readBuf)) {
amiDebugLog("Error : CheckSectorCRC error");
CloseHandle(hDevice);
return FALSE;
}
for (int local_218 = 0x10; readBuf[local_218] != 0; local_218 += 0x10) {
if (readBuf[local_218] == slotType) {
CloseHandle(hDevice);
return TRUE;
}
*pPartition = *pPartition + 1;
}
CloseHandle(hDevice);
return FALSE;
}
bool GetAppDataSlotDiskNumber(DWORD nDevice, short* pPartition) {
return GetSlotDiskNumber(nDevice, pPartition, 0x40) != FALSE;
}
bool GetOSSlotDiskNumber(DWORD nDevice, short* pPartition) {
return GetSlotDiskNumber(nDevice, pPartition, 0x30) != FALSE;
}
BOOL MountUpdate(DWORD nDevice) {
short nPartition;
if (!GetOSSlotDiskNumber(nDevice, &nPartition)) return FALSE;
char drive[256];
sprintf_s(drive, sizeof drive, "\\Device\\Harddisk%d\\Partition%d", nDevice, nPartition);
char szCommand[256];
snprintf(szCommand, sizeof szCommand, TRUECRYPT " /k %s /v %s /l %s /s /q", OS_UPDATE_KEY_FILE,
drive, UPDATE_MOUNT);
return RetryCommand(szCommand, 100, 200);
}
BOOL CheckIsRingRegistryPresent(BOOL* lpIsRing) {
HKEY hKey;
LSTATUS stat = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\SEGA\\RING\\GRAPHICS", 0,
KEY_QUERY_VALUE, &hKey);
if (stat == ERROR_SUCCESS) {
RegCloseKey(hKey);
*lpIsRing = TRUE;
return TRUE;
} else if (stat == ERROR_FILE_NOT_FOUND) {
*lpIsRing = FALSE;
return TRUE;
} else {
*lpIsRing = FALSE;
return FALSE;
}
}
BOOL _MountDriver(void) {
char szCommand[256];
snprintf(szCommand, sizeof szCommand, TRUECRYPT " /k %s /v %s /l %s /s /q", OS_UPDATE_KEY_FILE,
DEFAULT_DRIVERS, DRIVERS_MOUNT);
return RetryCommand(szCommand, 100, 200);
}
BOOL MountDriver(BOOL isRing) {
if (!isRing) return TRUE;
return _MountDriver();
}
typedef enum PLATFORM {
PLATFORM_RW = 0,
PLATFORM_RE = 1,
PLATFORM_RE2 = 2,
PLATFORM_UNK = 3,
} PLATFORM;
BOOL CheckPlatform(PLATFORM* lpPlatform) {
AM_PLATFORM_PLATFORM_ID_EX platform;
if (amPlatformGetPlatformIdEx(&platform) != AM_PLATFORM_STATUS_OK) {
*lpPlatform = PLATFORM_UNK;
return FALSE;
}
if (strcmp(platform.strPlatformId, PLATFORM_RINGEDGE) == 0) {
if (platform.platformId == 1) {
*lpPlatform = PLATFORM_RW;
return TRUE;
} else if (platform.platformId == 2) {
*lpPlatform = PLATFORM_RE;
return TRUE;
} else {
*lpPlatform = PLATFORM_UNK;
amiDebugLog("Error : Platform is unknown.");
return FALSE;
}
} else if (strcmp(platform.strPlatformId, PLATFORM_RINGWIDE) == 0) {
if (platform.platformId == 1) {
*lpPlatform = PLATFORM_RE2;
return TRUE;
} else {
*lpPlatform = PLATFORM_UNK;
amiDebugLog("Error : Platform is unknown.");
return FALSE;
}
} else {
*lpPlatform = PLATFORM_UNK;
amiDebugLog("Error : Platform is unknown.");
return FALSE;
}
}
BOOL ExecuteMxOSUpdate(BOOL isMasterRing) {
HINSTANCE result = NULL;
PLATFORM platform = PLATFORM_UNK;
if (!CheckPlatform(&platform)) return FALSE;
if (platform != PLATFORM_RW) {
if (platform == PLATFORM_RE) {
if (!PathFileExistsA(OS_UPDATE_CONF)) {
if (!isMasterRing) {
amiDebugLog("Error : Platform = EDGE2 but Master OS is not EDGE2");
return FALSE;
} else {
amiDebugLog("Execute %s", DRIVERS_UPDATE_EXE);
result =
ShellExecuteA(NULL, NULL, DRIVERS_UPDATE_EXE, NULL, DRIVERS_MOUNT_SLASH, 1);
return (int)result < 33 ? FALSE : TRUE;
}
} else {
amiDebugLog("Execute %s\n", UPDATE_EXE);
result = ShellExecuteA(NULL, NULL, UPDATE_EXE, NULL, UPDATE_MOUNT_SLASH, 1);
return (int)result < 33 ? FALSE : TRUE;
}
}
if (platform != PLATFORM_RE2) {
amiDebugLog("Error : Unknown platform");
return FALSE;
}
}
amiDebugLog("Execute %s", UPDATE_EXE);
result = ShellExecuteA(NULL, NULL, UPDATE_EXE, NULL, UPDATE_MOUNT_SLASH, 1);
return (int)result < 33 ? FALSE : TRUE;
}
BOOL ChangeEWFStateEnable(void) {
// TODO: Remove this once mice stubs EWF
return TRUE;
PEWF_VOLUME_NAME_ENTRY pProVolList = EwfMgrGetProtectedVolumeList();
if (pProVolList == NULL) {
amiDebugLog("Error : EwfMgrGetProtectedVolumeList error");
return FALSE;
}
while (!EwfMgrVolumeNameListIsEmpty(pProVolList)) {
WCHAR chDrive = EwfMgrGetDriveLetterFromVolumeName(pProVolList->Name);
if (chDrive == -1) {
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : EwfMgrGetDriveLetterFromVolumeName error");
return FALSE;
}
if (chDrive != L'C') {
EwfMgrVolumeNameEntryPop(&pProVolList);
continue;
}
HANDLE volHandle = EwfMgrOpenProtected(pProVolList->Name);
if (volHandle == INVALID_HANDLE_VALUE) {
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : EwfMgrOpenProtected error");
return FALSE;
}
if (!EwfMgrEnable(volHandle)) {
EwfMgrClose(volHandle);
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : EwfMgrEnable error");
return FALSE;
}
EwfMgrClose(volHandle);
EwfMgrVolumeNameListDelete(pProVolList);
return TRUE;
}
EwfMgrVolumeNameListDelete(pProVolList);
amiDebugLog("Error : Not Found Volume \"C:\\\"");
return FALSE;
}
BOOL MountAppDataPartition(DWORD diskNumber, short partitionNumber) {
char targetPath[256];
sprintf_s(targetPath, sizeof targetPath, "\\Device\\Harddisk%d\\Partition%d", diskNumber,
partitionNumber);
if (osuMountPartition(targetPath, "\\\\.\\Y:\\") != 0) {
amiDebugLog("Error : osuMountPartiotion error");
return FALSE;
}
return TRUE;
}
BOOL ExecCalcToAppData(void) {
for (int i = 0; i < 100; i++) {
int err = osuExecProcess("cacls y:\\ /t /e /p everyone:F");
if (err != -140) {
amiDebugLog("Error : osuExecProcess ErrCode = %n", err);
return TRUE;
}
Sleep(200);
}
return FALSE;
}
BOOL SetAppDataAccessPrivilege(DWORD diskNumber) {
short appDataPartition;
if (!GetAppDataSlotDiskNumber(diskNumber, &appDataPartition)) {
amiDebugLog("Error : GetAppDataDiskNumber error");
return FALSE;
}
if (!MountAppDataPartition(diskNumber, appDataPartition)) {
amiDebugLog("Error : MountAppDataPartition error");
return FALSE;
}
if (!ExecCalcToAppData()) {
amiDebugLog("Error : ExecCalcToAppData error");
return FALSE;
}
return TRUE;
}
void SetBackGroundColor(void) {
HKEY hkColors;
if (RegOpenKeyExA(HKEY_USERS, ".Default\\Control Panel\\Colors", 0, KEY_ALL_ACCESS,
&hkColors) != ERROR_SUCCESS) {
amiDebugLog("Error : RegOpenKeyExA failed.");
return;
}
if (RegSetValueExA(hkColors, "Background", 0, REG_SZ, (LPBYTE) "255 255 255",
strlen("255 255 255")) != ERROR_SUCCESS) {
amiDebugLog("Error : RegSetValueExA failed.");
}
RegCloseKey(hkColors);
return;
}
BOOL SetBackupComputerName() {
if (amEepromInit(NULL) != AM_EEPROM_STATUS_OK) {
amiDebugLog("Error : amEepromInit error");
return FALSE;
}
if (amBackupInit() != 0) {
amEepromExit();
amiDebugLog("Error : amBackupInit error");
return FALSE;
}
AM_BACKUP_RECORD* lpConfig = amBackupGetRecord(AM_BACKUP_RECORD_ALPB_COMPUTER_NAME);
AM_SYSDATAwH_ALPB_COMPUTER_NAME record;
int err = amBackupRecordReadDup(lpConfig, &record);
amBackupExit();
amEepromExit();
if (err != 0 || strlen(record.m_Name) == 0 || strlen(record.m_Name) > MAX_COMPUTERNAME_LENGTH)
return FALSE;
return SetComputerNameA(record.m_Name);
}
bool MxChangeActivePartition(BYTE partition) { return osuSetActivePartition(partition) == 0; }
MxError_t SystemUpdateStep2(DWORD diskNumber) {
AppendAsterisk();
SetDefaultShell();
AppendAsterisk();
if (!GetOSUpdateKeyFile()) {
amiDebugLog("Error : GetOSUpdateKeyFile error");
return MxError_OSUpdateKeyFile;
}
AppendAsterisk();
if (!MountUpdate(diskNumber)) {
amiDebugLog("Error : MountUpdate error");
return MxError_MountUpdate;
}
AppendAsterisk();
BOOL isRing = FALSE;
if (!CheckIsRingRegistryPresent(&isRing)) {
amiDebugLog("Error : CheckIsRingRegistryPresent error");
return MxError_RingRegistry;
}
AppendAsterisk();
if (!MountDriver(isRing)) {
amiDebugLog("Error : MountDriver error");
return MxError_MountDriver;
}
AppendAsterisk();
if (!DeleteFileA(OS_UPDATE_KEY_FILE)) {
amiDebugLog("Error : Deleate Key File error");
return MxError_SysKeyDelete;
}
AppendAsterisk();
if (!ExecuteMxOSUpdate(isRing)) {
amiDebugLog("Error : ExecuteMxOSUpdate error");
return MxError_ExecuteOSUpdate;
}
return MxError_None;
}
MxError_t SystemUpdateStep3(DWORD diskNumber) {
AppendAsterisk();
if (!ChangeEWFStateEnable()) {
amiDebugLog("Error : ChangeEWFStateEnable error");
return MxError_EWFEnable;
}
AppendAsterisk();
if (!SetAppDataAccessPrivilege(diskNumber)) {
amiDebugLog("Error : SetAppDataAccessPrivilege error");
return MxError_DiskAccessPrivilege;
}
AppendAsterisk();
SetBackGroundColor();
AppendAsterisk();
DeleteMounteDevices();
AppendAsterisk();
if (!SetBackupComputerName()) {
amiDebugLog("Error : SetBackupComputerName failed.");
}
AppendAsterisk();
SetDefaultShell();
AppendAsterisk();
EnterCriticalSection(&g_Top.criticalSection);
g_Bottom.status_str = "Reboot";
LeaveCriticalSection(&g_Top.criticalSection);
Sleep(3000);
AppendAsterisk();
if (!MxChangeActivePartition(1)) {
amiDebugLog("Error : MxChangeActivePartition error");
return MxError_ChangeActivePartition;
}
AppendAsterisk();
if (osuSystemReboot() != 0) {
amiDebugLog("Error : osuSystemReboot error");
return MxError_Reboot;
}
return MxError_None;
2022-10-30 17:33:02 +00:00
}
MxError_t NormalBootStep(void) {
AppendAsterisk();
if (!GetSystemKeyFile()) return MxError_NoKeyFile;
AppendAsterisk();
if (!TryMountSystemVolume()) return MxError_SystemMount;
AppendAsterisk();
if (!DeleteFileA(SYSTEM_KEY_FILE)) return MxError_SysKeyDelete;
AppendAsterisk();
if (!SetDiskAccessPrivilege()) return MxError_DiskAccessPrivilege;
AppendAsterisk();
if (!ExecuteMxMaster()) return MxError_MxMaster;
return MxError_None;
}
int DoStartup() {
StartupStep_t step = Init;
MxError_t error = MxError_None;
2023-07-16 21:13:34 +00:00
DWORD diskNumber = 0;
2022-10-30 17:33:02 +00:00
while (step != Done) {
printf("Step: %d (%d)\n", step, error);
switch (step) {
case Init:
if (!MxInitStartup(&diskNumber))
step = CheckEwf;
else
step = Done;
break;
case CheckEwf: {
AppendAsterisk();
EWF_STATE state;
if (!CheckEwfState(&state)) {
error = MxError_Ewf;
step = Done;
break;
}
if (state == EWF_ENABLED)
step = NormalBoot;
else
step = EwfDisabled;
break;
}
case EwfDisabled: {
char versionString[VERSION_BUFFER];
char defaultVersionString[VERSION_BUFFER];
if (!GetCurrentVersion(versionString) || !GetDefaultVersion(defaultVersionString)) {
error = MxError_Version;
step = Done;
break;
}
if (strcmp(versionString, defaultVersionString) == 0)
step = GetSBR;
else
step = SystemUpdate3;
break;
}
case GetSBR: {
int updateState;
AppendAsterisk();
if (!GetSBRSlotOSState(diskNumber, &updateState)) {
error = MxError_SBR;
step = Done;
break;
}
if (updateState == 2)
step = SystemUpdate2;
else
step = SystemUpdate3;
break;
}
case NormalBoot:
error = NormalBootStep();
step = Done;
break;
case SystemUpdate2:
setStrForStep2();
error = SystemUpdateStep2(diskNumber);
step = Done;
break;
case SystemUpdate3:
setStrForStep3();
error = SystemUpdateStep3(diskNumber);
step = Done;
break;
default:
error = MxError_Unknown;
step = Done;
break;
}
}
return error;
}
2023-07-16 21:13:34 +00:00
bool ExitGraphics(void) {
if (!osgExit(&g_Osu)) {
amiDebugLog("Error : osgExit error");
return false;
}
return true;
2022-10-30 17:33:02 +00:00
}
2023-07-16 21:13:34 +00:00
void DisplayError(MxError_t err) {
static char message[32];
message[0] = '\0';
sprintf_s(message, sizeof message, "Error %d", err);
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
EnterCriticalSection(&g_Top.criticalSection);
g_Bottom.status_str = message;
g_Bottom.status_use_counter = 0;
g_Bottom.status_colour = Red;
g_Bottom.str2 = "";
g_Bottom.hide_power = 0;
LeaveCriticalSection(&g_Top.criticalSection);
2022-10-30 17:33:02 +00:00
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
PVOID old = NULL;
Wow64DisableWow64FsRedirection(&old);
2023-07-16 21:13:34 +00:00
// TODO: Remove this
nShowCmd = 1;
if (!InitGraphics(hInstance, nShowCmd)) amiDebugLog("Error : InitGraphics failed.");
g_Bottom.backgroundColour = Green;
g_Top.str1 = "MxDraw Demo";
g_Top.str2 = "owo what's this";
g_Bottom.status_str = "I blink!!";
g_Bottom.str2 = "TURN OFF THE POWER, IF YOU DARE";
g_Bottom.line5 = "Look mum I'm an asteri************";
g_Bottom.debug_text = "Debug text goes here, but nothing uses me!!";
while (1) {
g_Top.show_top = TRUE;
g_Top.debugEnable = TRUE;
Sleep(100);
2022-10-30 17:33:02 +00:00
}
2023-07-16 21:13:34 +00:00
Sleep(10000);
2022-10-30 17:33:02 +00:00
2023-07-16 21:13:34 +00:00
if (!amLogInit()) {
2022-10-30 17:33:02 +00:00
LOG_EN_PLATFORM = 1;
2023-07-16 21:13:34 +00:00
AM_LOG_OPTION logMxStartup = {
.m_EventCategory = 1,
.m_EventId = 1,
.m_EventSource = "mxstartup",
.m_EventType = 1,
};
amLogSetEventOption(&logMxStartup);
amiDebugSetCallback(amLogReportEvent);
2022-10-30 17:33:02 +00:00
}
MxError_t err = DoStartup();
if (!err) {
2023-07-16 21:13:34 +00:00
if (!ExitGraphics()) amiDebugLog("Error : ExitGraphics failed.");
amLogFinalize();
2022-10-30 17:33:02 +00:00
return 0;
}
2023-07-16 21:13:34 +00:00
while (1) {
DisplayError(err);
Sleep(100000);
}
2022-10-30 17:33:02 +00:00
return 0;
}
int main() { return WinMain(NULL, NULL, NULL, 0); }