micetools/src/micetools/micemaster/mxmEventLog.c

434 lines
13 KiB
C

#include "mxmEventLog.h"
#include <Windows.h>
#include <stdio.h>
#include <winioctl.h>
#include "../lib/ami/amiMd5.h"
mxmEventLog_t MxmEventLog;
#define LOG_DRIVE "L:\\"
#define LOG_VOLUME "\\\\.\\L:\\"
#define LOG_DRIVE_NAME "SEGA_AM_LOG"
#define TEMP_PATH "C:\\WINDOWS\\TEMP\\"
bool mxmEventLogGetTempPath(char *name, char *buffer) {
SYSTEMTIME now;
GetLocalTime(&now);
_snprintf_s(buffer, 0x104, 0xffffffff, "%s%s%04d%02d%02d%02d%02d%02d.evt", TEMP_PATH, name,
now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond);
return true;
}
bool mxmEventLogGetLogDrive(char *logPath) {
char volumeName[264];
if (GetVolumeInformationA(LOG_VOLUME, volumeName, 264, NULL, NULL, NULL, NULL, 0)) {
if (strcmp(volumeName, LOG_DRIVE_NAME) == 0) {
strncpy_s(logPath, MAX_PATH, LOG_DRIVE, _TRUNCATE);
return true;
}
}
return false;
}
int mxmEventLogSetDestination(char *name, unsigned int which) {
char *type_names[NUM_LOGS];
SYSTEMTIME now;
type_names[0] = "application";
type_names[1] = "security";
type_names[2] = "system";
if (name == NULL || which >= NUM_LOGS) return -1;
GetLocalTime(&now);
_snprintf_s(MxmEventLog.m_desinations[which].m_filename, MAX_PATH, _TRUNCATE,
"%s%s%04d%02d%02d%02d%02d%02d.evt", name, type_names[which], now.wYear, now.wMonth,
now.wDay, now.wHour, now.wMinute, now.wSecond);
return 0;
}
void mxmEventLogInit(void) {
if (MxmEventLog.m_filenamesSet) return;
char name[268];
name[0] = '\0';
MxmEventLog.m_logDriveFound = mxmEventLogGetLogDrive(name);
if (MxmEventLog.m_logDriveFound) {
for (int i = 0; i < NUM_LOGS; i++) mxmEventLogSetDestination(name, i);
MxmEventLog.m_filenamesSet = true;
}
}
bool mxmEventLogEraseLog(void) {
AM_INSTALL_BOOT_RECORD br;
ZeroMemory(&br, sizeof br);
int devNum = 0;
if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false;
if (!mxmEventLogAccessLoadEpbr(&br)) return false;
if (!mxmEventLogAccessEraseEventLogData(devNum, br.os)) return false;
return true;
}
bool mxmEventLogCheckLog(bool *valid) {
if (valid == NULL) return false;
AM_INSTALL_BOOT_RECORD br;
ZeroMemory(&br, sizeof br);
int devNum = 0;
if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false;
if (!mxmEventLogAccessLoadEpbr(&br)) return false;
if (!mxmEventLogAccessCheckEventLogData(devNum, br.os, valid)) return false;
return true;
}
bool mxmEventLogAccessGetMainStorageDeviceNum(int *devNum) {
if (devNum == NULL) {
amiDebugLog("Error : Invalid Argument");
return false;
}
char windir[256];
if (!GetSystemWindowsDirectoryA(windir, sizeof windir)) {
amiDebugLog("Error : GetSystemWindowsDirectoryA error");
*devNum = -1;
return false;
}
char windirDos[256];
sprintf_s(windirDos, sizeof windirDos, "\\\\.\\%c:", windir[0]);
HANDLE hDevice =
CreateFileA(windirDos, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
amiDebugLog("Error : CreateFile error ErrorNum = %d", GetLastError());
*devNum = -1;
return false;
}
STORAGE_DEVICE_NUMBER ioctlBuf;
DWORD bytesReturned;
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &ioctlBuf,
sizeof ioctlBuf, &bytesReturned, NULL)) {
amiDebugLog("Error : DeviceIoControl error ErrorNum = %d", GetLastError());
CloseHandle(hDevice);
*devNum = -1;
return false;
}
CloseHandle(hDevice);
*devNum = ioctlBuf.DeviceNumber;
return true;
}
bool mxmEventLogAccessEraseEventLogData(int deviceNum, unsigned long long address) {
char drivePath[MAX_PATH];
ZeroMemory(drivePath, sizeof drivePath);
sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum);
HANDLE hFile =
CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
amiDebugLog("Error : CreateFile error");
return false;
}
char logBuffer[512];
ZeroMemory(logBuffer, sizeof logBuffer);
LARGE_INTEGER writeAddress;
writeAddress.QuadPart = address + LOG_OFFSET;
if (!SetFilePointerEx(hFile, writeAddress, NULL, FILE_BEGIN)) {
CloseHandle(hFile);
amiDebugLog("SetFilePointerEx error");
return false;
}
DWORD bytesWritten;
if (!WriteFile(hFile, logBuffer, sizeof logBuffer, &bytesWritten, NULL)) {
CloseHandle(hFile);
amiDebugLog("WriteFile error %d", GetLastError());
return false;
}
if (bytesWritten != sizeof logBuffer) {
CloseHandle(hFile);
amiDebugLog("Wriete Size Error");
return false;
}
CloseHandle(hFile);
return true;
}
bool mxmEventLogAccessCheckEventLogData(int deviceNum, unsigned long long address, bool *valid) {
AM_EVENT_LOG_HEADER logHeader;
char drivePath[MAX_PATH];
ZeroMemory(&logHeader, sizeof logHeader);
ZeroMemory(drivePath, sizeof drivePath);
sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum);
HANDLE hFile =
CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
amiDebugLog("Error : CreateFile error");
return false;
}
LARGE_INTEGER writeAddress;
writeAddress.QuadPart = address + LOG_OFFSET;
if (!SetFilePointerEx(hFile, writeAddress, NULL, FILE_BEGIN)) {
CloseHandle(hFile);
amiDebugLog("SetFilePointerEx error");
return false;
}
DWORD bytesRead;
if (!ReadFile(hFile, &logHeader, sizeof logHeader, &bytesRead, NULL)) {
CloseHandle(hFile);
amiDebugLog("ReadFile Header error");
return false;
}
if (bytesRead != sizeof logHeader) {
CloseHandle(hFile);
amiDebugLog("Read Size Error");
return false;
}
amiCrc32RInit();
unsigned int calcCrc =
amiCrc32RCalc(sizeof logHeader - 4, (unsigned char *)(&logHeader) + 4, 0);
*valid = logHeader.m_crc32 == calcCrc;
CloseHandle(hFile);
return true;
}
bool mxmEventLogAccessLoadEpbr(AM_INSTALL_BOOT_RECORD *bootRecord) {
amtime_t start, now;
AM_INSTALL_STATUS err = amInstallInit();
if (err != AM_INSTALL_STATUS_OK && err != AM_INSTALL_STATUS_ERR_ALREADY_INIT) {
amiDebugLog("Error : amInstallInit. Code %d", err);
return false;
}
amiTimerGet(&start);
while (1) {
err = amInstallGetBr(bootRecord, 0);
if (!((err == AM_INSTALL_STATUS_ERR_REQUEST) ||
(err == AM_INSTALL_STATUS_ERR_UPDATE_STATUS) ||
(err == AM_INSTALL_STATUS_ERR_GET_SEMAPHORE) ||
(err == AM_INSTALL_STATUS_ERR_FORMAT) || (err == AM_INSTALL_STATUS_OK) ||
(err == AM_INSTALL_STATUS_BUSY))) {
amiDebugLog("Error : amInstallGetBr error.");
amInstallExit();
return false;
}
amiTimerGet(&now);
if (amiTimerDiffSec(&start, &now) > 30) {
amiDebugLog("Error : amInstallGetBr time out error.");
amInstallExit();
return false;
}
if (err == AM_INSTALL_STATUS_OK) {
if (amInstallExit() == AM_INSTALL_STATUS_OK) return true;
amiDebugLog("Error : amInstallExit.");
return false;
}
}
}
bool mxmEventLogAccessReadEventLogData(int deviceNum, unsigned long long address,
unsigned char *eventlog1, unsigned int *nBytes1,
unsigned char *eventlog2, unsigned int *nBytes2) {
if (nBytes1 == 0 || eventlog2 == NULL || nBytes2 == NULL) return false;
AM_EVENT_LOG_HEADER eventLogHeader;
ZeroMemory(&eventLogHeader, sizeof eventLogHeader);
char drivePath[256];
ZeroMemory(&drivePath, sizeof drivePath);
sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum);
HANDLE hFile =
CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
amiDebugLog("Error : CreateFile error");
return false;
}
LARGE_INTEGER readAddress;
readAddress.QuadPart = address + LOG_OFFSET;
if (!SetFilePointerEx(hFile, readAddress, NULL, 0)) {
CloseHandle(hFile);
amiDebugLog("SetFilePointerEx error");
return false;
}
DWORD bytesRead;
if (!ReadFile(hFile, &eventLogHeader, sizeof eventLogHeader, &bytesRead, NULL)) {
CloseHandle(hFile);
amiDebugLog("ReadFile Header error");
return false;
}
if (bytesRead != sizeof eventLogHeader) {
CloseHandle(hFile);
amiDebugLog("Read Size error");
return false;
}
amiCrc32RInit();
unsigned int calcCrc =
amiCrc32RCalc(sizeof eventLogHeader - 4, (unsigned char *)(&eventLogHeader) + 4, 0);
if (calcCrc != eventLogHeader.m_crc32) {
CloseHandle(hFile);
return false;
}
if (eventLogHeader.m_nBytes[0] > LOG_MAX_SIZE || eventLogHeader.m_nBytes[1] > LOG_MAX_SIZE) {
CloseHandle(hFile);
amiDebugLog("Buffer Size error");
return false;
}
unsigned char *readBuffer = malloc(LOG_MAX_SIZE);
if (readBuffer == NULL) {
CloseHandle(hFile);
return false;
}
ZeroMemory(readBuffer, LOG_MAX_SIZE);
struct {
unsigned long long offset;
unsigned int srcSize;
unsigned int dstSize;
unsigned char *dst;
} readSetup[2] = {
{
.offset = LOG_1_OFFSET,
.dstSize = LOG_MAX_SIZE,
.dst = eventlog1,
},
{
.offset = LOG_2_OFFSET,
.dstSize = LOG_MAX_SIZE,
.dst = eventlog2,
},
};
for (int i = 0; i < 2; i++) {
readAddress.QuadPart = address + readSetup[i].offset;
if (!SetFilePointerEx(hFile, readAddress, NULL, 0)) {
free(readBuffer);
CloseHandle(hFile);
amiDebugLog("SetFilePointerEx error");
return false;
}
DWORD nRead = eventLogHeader.m_nBytes[i];
if ((nRead & 0x1FF) != 0) nRead += 512 - (nRead & 0x1FF);
if (!ReadFile(hFile, readBuffer, nRead, &bytesRead, NULL)) {
free(readBuffer);
CloseHandle(hFile);
amiDebugLog("ReadFile Evt error");
return false;
}
if (nRead != bytesRead) {
free(readBuffer);
CloseHandle(hFile);
amiDebugLog("Read Size error");
return false;
}
AmiMd5 md5;
amiMd5Init(&md5);
amiMd5Update(&md5, nRead, readBuffer);
amiMd5Finalise(&md5);
if (memcmp(md5.m_digest, eventLogHeader.m_md5[i], sizeof md5.m_digest) != 0) {
free(readBuffer);
CloseHandle(hFile);
amiDebugLog("Event Log is broken");
return false;
}
memcpy(readSetup[i].dst, readBuffer, readSetup[i].dstSize);
}
free(readBuffer);
CloseHandle(hFile);
return true;
}
DWORD mxmEventLogAccessWriteDataFile(char *filename, unsigned char *dataFile, unsigned int nBytes) {
HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_SUPPORTS_REPARSE_POINTS, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
amiDebugLog("Error : CreateFile error");
return (DWORD)-1;
}
DWORD ret = (DWORD)-1;
DWORD bytesRead;
if (WriteFile(hFile, dataFile, nBytes, &bytesRead, NULL)) {
ret = bytesRead;
}
CloseHandle(hFile);
return ret;
}
bool mxmEventLogAccessCopyIntoDataFile(int deviceNum, unsigned long long address, char *filename,
unsigned int type) {
unsigned int nBytes1;
unsigned char *eventLog1 = malloc(LOG_MAX_SIZE);
if (eventLog1 == NULL) return false;
unsigned int nBytes2;
unsigned char *eventLog2 = malloc(LOG_MAX_SIZE);
if (eventLog2 == NULL) {
free(eventLog1);
return false;
}
if (!mxmEventLogAccessReadEventLogData(deviceNum, address, eventLog1, &nBytes1, eventLog2,
&nBytes2)) {
free(eventLog1);
free(eventLog2);
return false;
}
bool success;
if (type == 0) {
success = mxmEventLogAccessWriteDataFile(filename, eventLog2, nBytes1);
} else if (type == 1) {
success = mxmEventLogAccessWriteDataFile(filename, eventLog2, nBytes2);
} else {
free(eventLog1);
free(eventLog2);
return false;
}
free(eventLog1);
free(eventLog2);
if (success == (DWORD)-1) return false;
return true;
}
bool mxmEventLogAccessBackup(char *filename, int type) {
AM_INSTALL_BOOT_RECORD br;
ZeroMemory(&br, sizeof br);
int devNum = 0;
if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false;
if (!mxmEventLogAccessLoadEpbr(&br)) return false;
if (!mxmEventLogAccessCopyIntoDataFile(devNum, br.os, filename, type)) return false;
return true;
}