1147 lines
36 KiB
C
1147 lines
36 KiB
C
#include <Windows.h>
|
|
#include <shellapi.h>
|
|
#include <shlwapi.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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"
|
|
#include "ewfapi.h"
|
|
#include "osg.h"
|
|
#include "osu.h"
|
|
|
|
typedef enum {
|
|
MxError_Unknown = -1,
|
|
MxError_None = 0,
|
|
|
|
MxError_SecurityCheck = 500,
|
|
MxError_Ewf = 501,
|
|
MxError_Version = 502,
|
|
MxError_NoKeyFile = 503,
|
|
MxError_DiskAccessPrivilege = 504,
|
|
MxError_SystemMount = 505,
|
|
MxError_MountUpdate = 506,
|
|
MxError_MxMaster = 507,
|
|
MxError_OSUpdateKeyFile = 508,
|
|
MxError_ExecuteOSUpdate = 509,
|
|
MxError_EWFEnable = 510,
|
|
MxError_SBR = 511,
|
|
MxError_SysKeyDelete = 512,
|
|
MxError_MountDriver = 513,
|
|
MxError_RingRegistry = 514,
|
|
|
|
MxError_UnMountVolume = 540,
|
|
MxError_MountRecovery = 541,
|
|
MxError_ChangeActivePartition = 543,
|
|
MxError_Reboot = 545,
|
|
MxError_GetCD = 546,
|
|
} 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"
|
|
#define DEFAULT_DRIVERS "Z:\\Minint\\System32\\DEFAULT_DRIVERS"
|
|
#define SYSTEM_MOUNT "S:"
|
|
#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"
|
|
|
|
#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"
|
|
|
|
#define TRUECRYPT "TrueCrypt"
|
|
|
|
// 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);
|
|
}
|
|
|
|
BOOL isDebugEnabled(void) {
|
|
WIN32_FIND_DATAA find;
|
|
HANDLE hFind;
|
|
|
|
hFind = FindFirstFileA(".\\DebugEnable", &find);
|
|
if (hFind != INVALID_HANDLE_VALUE) {
|
|
FindClose(hFind);
|
|
return TRUE;
|
|
}
|
|
FindClose(hFind);
|
|
return FALSE;
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
} else {
|
|
RegCloseKey(hkResult);
|
|
return White;
|
|
}
|
|
}
|
|
|
|
OSU_TOP g_Top;
|
|
OSU_BOTTOM g_Bottom;
|
|
OSU g_Osu;
|
|
|
|
#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);
|
|
}
|
|
|
|
/* 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) {
|
|
amiDebugLog("Error : GetVersionText error path = %s", path);
|
|
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];
|
|
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);
|
|
|
|
int ret = osuExecProcess(command);
|
|
if (ret == 0) return true;
|
|
amiDebugLog("Error : osuExecProcess error. ret = %d", ret);
|
|
return false;
|
|
}
|
|
/* Try to mount the system volume with up to 100 retries (20 seconds) */
|
|
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 */
|
|
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");
|
|
return false;
|
|
}
|
|
|
|
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");
|
|
return false;
|
|
}
|
|
|
|
CHAR readBuffer[260];
|
|
DWORD nRead;
|
|
if (!ReadFile(hSrc, readBuffer, 255, &nRead, NULL)) {
|
|
CloseHandle(hSrc);
|
|
CloseHandle(hDst);
|
|
amiDebugLog("Error : ReadFile error");
|
|
return false;
|
|
}
|
|
readBuffer[nRead] = '\0';
|
|
|
|
DWORD written;
|
|
bool ret = WriteFile(hDst, readBuffer, strlen(readBuffer), &written, NULL) != 0;
|
|
if (!ret) amiDebugLog("Error : WriteFile error");
|
|
CloseHandle(hSrc);
|
|
CloseHandle(hDst);
|
|
return ret;
|
|
}
|
|
void DeleteMounteDevices(void) {
|
|
if (RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SYSTEM\\MountedDevices") != ERROR_SUCCESS)
|
|
amiDebugLog("Error : RegDeleteKeyA failed.");
|
|
}
|
|
|
|
bool GetSystemKeyFile() { return GetKeyFile(SYSTEM_KEYFILE_ADS, SYSTEM_KEY_FILE); };
|
|
bool GetOSUpdateKeyFile() { return GetKeyFile(OS_UPDATE_KEYFILE_ADS, OS_UPDATE_KEY_FILE); };
|
|
bool SetDiskAccessPrivilege() {
|
|
int i;
|
|
for (i = 0; i < 100; i++) {
|
|
if (osuExecProcess(CACLS_REMPERM_EXECUTE) != -140) break;
|
|
Sleep(200);
|
|
}
|
|
if (i == 100) {
|
|
amiDebugLog("Error : osuExecProcess error");
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
if (osuExecProcess(CACLS_REMPERM_Z) != -140) break;
|
|
Sleep(200);
|
|
}
|
|
if (i == 100) {
|
|
amiDebugLog("Error : osuExecProcess error");
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
if (osuExecProcess(CACLS_REMPERM_S) != -140) break;
|
|
Sleep(200);
|
|
}
|
|
if (i == 100) {
|
|
amiDebugLog("Error : osuExecProcess error");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
bool ExecuteMxMaster() {
|
|
HINSTANCE ret = ShellExecuteA(NULL, NULL, NEXT_HOP_MXMASTER, NULL, NEXT_HOP_CWD, 0);
|
|
if ((int)ret < 33) {
|
|
amiDebugLog("Error : ShellExecute ret = %d", ret);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
BOOL SecurityCheck(void) {
|
|
AM_PLATFORM_BOARD_TYPE board_type;
|
|
if (amPlatformGetBoardType(&board_type) != AM_PLATFORM_STATUS_OK) {
|
|
amiDebugLog("Error : amPlatformGetBoardType error");
|
|
return FALSE;
|
|
}
|
|
|
|
if (board_type == AM_PLATFORM_BOARD_TYPE_UNKNOWN) {
|
|
amiDebugLog("Error : BoardType is unknown.");
|
|
return FALSE;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
DWORD diskNumber = 0;
|
|
|
|
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;
|
|
}
|
|
|
|
bool ExitGraphics(void) {
|
|
if (!osgExit(&g_Osu)) {
|
|
amiDebugLog("Error : osgExit error");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void DisplayError(MxError_t err) {
|
|
static char message[32];
|
|
message[0] = '\0';
|
|
sprintf_s(message, sizeof message, "Error %d", err);
|
|
|
|
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);
|
|
}
|
|
|
|
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
|
|
PVOID old = NULL;
|
|
Wow64DisableWow64FsRedirection(&old);
|
|
|
|
// 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);
|
|
}
|
|
Sleep(10000);
|
|
|
|
if (!amLogInit()) {
|
|
LOG_EN_PLATFORM = 1;
|
|
AM_LOG_OPTION logMxStartup = {
|
|
.m_EventCategory = 1,
|
|
.m_EventId = 1,
|
|
.m_EventSource = "mxstartup",
|
|
.m_EventType = 1,
|
|
};
|
|
amLogSetEventOption(&logMxStartup);
|
|
amiDebugSetCallback(amLogReportEvent);
|
|
}
|
|
|
|
MxError_t err = DoStartup();
|
|
if (!err) {
|
|
if (!ExitGraphics()) amiDebugLog("Error : ExitGraphics failed.");
|
|
amLogFinalize();
|
|
return 0;
|
|
}
|
|
|
|
while (1) {
|
|
DisplayError(err);
|
|
Sleep(100000);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main() { return WinMain(NULL, NULL, NULL, 0); }
|