JurassicParkTrespasser/jp2_pc/Source/Trespass/main.cpp

1221 lines
30 KiB
C++

//+--------------------------------------------------------------------------
//
// Copyright (C) DreamWorks Interactive, 1997.
//
// File: main.cpp
//
// Contents: WinMain window handler routine
//
// Classes:
//
// Functions:
//
// History: 21-Oct-97 SHernd Created
//
//---------------------------------------------------------------------------
#include "precomp.h"
#pragma hdrstop
#include <time.h>
#include <ShlObj.h>
#include "resource.h"
#include "main.h"
#include "../Lib/Sys/reg.h"
#include "../Lib/Sys/RegInit.hpp"
#include "Lib/Sys/Permissions.hpp"
#include "Lib/Sys/FileEx.hpp"
#include "supportfn.hpp"
#include "Lib/View/DisplayMode.hpp"
#include "tpassglobals.h"
#include "gblinc/buildver.hpp"
#include "Lib/W95/Direct3DCards.hpp"
#include "version.hpp"
#include <filesystem>
#if TARGET_PROCESSOR == PROCESSOR_PENTIUM
#pragma message("Target build processor : Intel Pentium")
#elif TARGET_PROCESSOR == PROCESSOR_PENTIUMPRO
#pragma message("Target build processor : Intel Pentium Pro / Pentium II")
#elif TARGET_PROCESSOR == PROCESSOR_K6_3D
#pragma message("Target build processor : AMD-K6 3D")
#endif
//+--------------------------------------------------------------------------
//------------------------- Globals ------------------------------
//---------------------------------------------------------------------------
HINSTANCE g_hInst = NULL;
HWND g_hwnd = NULL;
char g_szAppName[] = "DWI - Trespasser";
char g_szTitle[255];
UINT g_uiRegMsg;
CMainWnd * g_pMainWnd;
bool bUseOutputFiles = FALSE;
bool bUseReplayFile = TRUE;
bool g_bRestartWithRenderDlg = FALSE;
bool bIsTrespasser = true;
extern bool bUseGDIForMessages;
BOOL CALLBACK SiblingFindProc(HWND hwnd, LPARAM lParam)
{
SendMessage(hwnd, lParam, 0, 0);
return TRUE;
}
void FindRunningApp(LPARAM lMsgName)
{
EnumWindows((WNDENUMPROC)SiblingFindProc, lMsgName);
}
std::filesystem::path OpenDirectoryChooser(const std::filesystem::path& defaultPath)
{
CCom<IFileDialog> dlg = nullptr;
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dlg))) || !dlg)
return {};
FILEOPENDIALOGOPTIONS options;
if (FAILED(dlg->GetOptions(&options)))
return {};
options |= FOS_PICKFOLDERS;
options |= FOS_PATHMUSTEXIST;
if (FAILED(dlg->SetOptions(options)))
return {};
CCom<IShellItem> startPathItem = nullptr;
if (SUCCEEDED(SHCreateItemFromParsingName(defaultPath.wstring().c_str(), nullptr, IID_PPV_ARGS(&startPathItem))))
dlg->SetDefaultFolder(startPathItem); //Can ignore error here
if (FAILED(dlg->Show(g_hwnd)))
return {};
CCom<IShellItem> selected = nullptr;
if (FAILED(dlg->GetResult(&selected)) || !selected)
return {};
PWSTR pathstring = nullptr;
if (FAILED(selected->GetDisplayName(SIGDN_FILESYSPATH, &pathstring)) || !pathstring)
return {};
std::filesystem::path result = pathstring;
CoTaskMemFree(pathstring);
return result;
}
//+--------------------------------------------------------------------------
//
// Function: GetModulePath
//
// Synopsis: Returns the path (no file name) of the instance specified.
//
// Arguments: [hInst] -- instance to return the path of
// [pszDst] -- buffer to place the path in
// [cch] -- size of the path
//
// Returns: int - length of the string placed in the buffer
//
// History: 10-Oct-95 SHernd Created
//
//---------------------------------------------------------------------------
int GetModulePath(HINSTANCE hInst, LPSTR pszDst, int cch)
{
char sz[_MAX_PATH];
char sz2[_MAX_PATH];
char szDrive[_MAX_DRIVE];
GetModuleFileName(g_hInst, sz, cch);
_splitpath(sz, szDrive, sz2, NULL, NULL);
strcpy(sz, szDrive);
strcat(sz, sz2);
strcpy(pszDst, sz);
return strlen(pszDst);
}
void SetProperWorkingDir()
{
char szPath[_MAX_PATH];
#if VER_TEST
GetFileLoc(FA_INSTALLDIR, szPath, sizeof(szPath));
#else
GetModulePath(g_hInst, szPath, sizeof(szPath));
#endif
Trace(("%s", szPath));
//SetCurrentDirectory would default to C:\ with empty input
//Backslash was appended by GetFileLoc
if (szPath[0] != '\0' && strcmp(szPath, "\\") != 0)
SetCurrentDirectory(szPath);
}
//+--------------------------------------------------------------------------
//
// Function: bRunSafeMode
//
// Synopsis: Sets settings to run safemode.
//
// Arguments: None.
//
// Returns: None.
//
// History: 8-July-98 PKeet
//
//---------------------------------------------------------------------------
bool bRunSafeMode()
{
// Display dialog.
int i_retval = MsgDlg(g_hwnd, MB_YESNOCANCEL | MB_ICONQUESTION, IDS_TITLE, IDS_SAFEMODE);
if (i_retval == IDNO)
{
DisableSafemode();
return false;
}
// Exit the application if 'Cancel' is selected.
if (i_retval == IDCANCEL)
{
return true;
}
// Conservative, non-hardware accelerated settings.
SetD3D(FALSE);
SetDimensions(640, 480);
bSetInitFlag(TRUE);
SetAutoLoad(FALSE);
// Delete Registry Keys.
DeleteValue(strD3D_TITLE);
DeleteValue(strFLAG_D3D);
DeleteValue(strD3D_FILTERCACHES);
DeleteValue(strVIDEOCARD_TYPE);
DeleteValue(strVIDEOCARD_NAME);
DeleteValue(strDDDEVICE_NAME);
DeleteValue(strDDDEVICE_DESCRIPTION);
DeleteValue(strDDDEVICE_GUID);
DeleteValue(strD3DDEVICE_NAME);
DeleteValue(strD3DDEVICE_DESCRIPTION);
DeleteValue(strD3DDEVICE_GUID);
SetAutoLoad(FALSE);
// Set new conservative audio values.
SetRegValue(REG_KEY_AUDIO_EFFECT, 0);
SetRegValue(REG_KEY_AUDIO_AMBIENT, 0);
SetRegValue(REG_KEY_AUDIO_VOICEOVER, 0);
SetRegValue(REG_KEY_AUDIO_MUSIC, 0);
SetRegValue(REG_KEY_AUDIO_SUBTITLES, 1);
SetRegValue(REG_KEY_AUDIO_ENABLE3D, 0);
return false;
}
//+--------------------------------------------------------------------------
//
// Function: SetSpeedDefaults
//
// Synopsis: Sets settings to run based on detected CPU speed. Will not
// change already stored settings.
//
// Arguments: None.
//
// Returns: None.
//
// History: 8-July-98 PKeet
//
//---------------------------------------------------------------------------
void SetSpeedDefaults()
{
// Ignore these defaults if safe mode is active.
if (bSafemode())
return;
if (bAutoSettings(true))
{
Trace(("Settings for machine already performed...\n"));
return;
}
// Set defaults.
SetRegValue(REG_KEY_RENDERING_QUALITY, DEFAULT_RENDERING_QUALITY);
SetDimensions(320, 240);
// Get the cpu speed.
uint32 u4_mhz = u4GetCPUSpeed();
Trace(("Machine CPU speed: %ld\n", u4_mhz));
// There is a mistake if cpu speed is null or very small.
if (u4_mhz < 10)
{
Trace(("Error in autosettings for machine...\n"));
}
// Slow machine settings.
if (u4_mhz < 220)
{
SetRegValue(REG_KEY_RENDERING_QUALITY, 2);
SetDimensions(320, 240);
Trace(("Set for slow machine...\n"));
return;
}
// Moderate speed machines.
if (u4_mhz < 280)
{
SetRegValue(REG_KEY_RENDERING_QUALITY, 3);
SetDimensions(400, 300);
Trace(("Set for moderate machine...\n"));
return;
}
// Fastest machines.
SetRegValue(REG_KEY_RENDERING_QUALITY, 3);
SetDimensions(512, 384);
Trace(("Set for fastest machine...\n"));
}
//+--------------------------------------------------------------------------
//
// Function: TrespassExceptionCleanup
//
// Synopsis: When an exception is trapped in WinMain this code gets called
// to clean up as much as possible for the app to terminally
// fail gracefully.
//
// Returns: void
//
// History: 19-Aug-98 SHernd Created
//
//---------------------------------------------------------------------------
void TrespassExceptionCleanup()
{
ForceShowCursor(TRUE);
ClipCursor(NULL);
// Remove the audio, we are about to quit.
delete CAudio::pcaAudio;
std::destroy_at(&prasMainScreen);
g_initDD.ReleaseAll();
if (g_hwnd)
{
DestroyWindow(g_hwnd);
g_hwnd = 0;
}
delete g_pMainWnd;
g_pMainWnd = NULL;
CoUninitialize();
ErrorDlg(g_hwnd, IDS_ERROR_FATAL);
ExitProcess(0);
}
bool ValidateDiskSpace(int iMB)
{
char szPath[_MAX_PATH] = { '\0' };
GetFileLoc(FA_INSTALLDIR, szPath, sizeof(szPath));
const auto diskstat = std::filesystem::space(szPath);
//Existing swp files count as free space
std::uintmax_t swpFilesSize = 0;
for (const auto& entry : std::filesystem::directory_iterator("."))
if (entry.is_regular_file() && entry.path().extension() == ".swp")
swpFilesSize += entry.file_size();
const std::uintmax_t neededBytes = iMB * static_cast<std::uintmax_t>(1024 * 1024);
return diskstat.free + swpFilesSize > neededBytes;
}
bool TestDataDriveValidity()
{
bool validatedDataDrive = false;
while (!validatedDataDrive)
{
char sz[_MAX_PATH];
GetFileLoc(FA_DATADRIVE, sz, sizeof(sz));
std::filesystem::path datapath = sz;
// This should be the unique file on the disk
if (!std::filesystem::exists(datapath / "menu" / "tpassintro.smk"))
{
//Without the data subpath
auto datadrive = datapath.has_parent_path() ? datapath.parent_path() : datapath;
if (datadrive.has_parent_path() && datadrive.has_stem() && datadrive.stem() == "data"
&& std::filesystem::exists(datadrive / "menu" / "tpassintro.smk"))
{
//We are in the data directory itself, correct to parent directory
auto parent = datadrive.parent_path();
SetRegString(REG_KEY_DATA_DRIVE, parent.string().c_str());
return true;
}
if (MsgDlg(g_hwnd,
MB_YESNOCANCEL | MB_SETFOREGROUND,
IDS_ERROR_TITLE,
IDS_DATA_DRIVE_NOT_FOUND,
datadrive.string().c_str()) != IDYES)
{
Trace(("We are Cancelling from no data found"));
return false;
}
auto newpath = OpenDirectoryChooser(datadrive);
if (!newpath.empty())
SetRegString(REG_KEY_DATA_DRIVE, newpath.string().c_str());
}
else
validatedDataDrive = true;
}
return true;
}
//+--------------------------------------------------------------------------
//
// Function: DoWinMain
//
// Synopsis: Extra WinMain handler. This exists because of the
// __try/__finally block in WinMain
//
// Arguments: [hInstance] --
// [hPrevInstance] --
// [lpCmdLine] --
// [nCmdShow] --
//
// Returns: int
//
// History: 19-Aug-98 SHernd Created
//
//---------------------------------------------------------------------------
int DoWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int iRet = 0;
HANDLE hMutex;
int i;
bool bVideoCardChosen;
BOOL b_change_safemode = TRUE;
CoInitialize(nullptr);
// Make sure the cursor can access the safe mode dialog.
ClipCursor(0);
g_hInst = hInstance;
bUseGDIForMessages = false;
OpenKey();
SetProperWorkingDir();
if (!bCanCreateFile("permissiontestfile.txt") && !IsProcessElevated()) {
if (!StartAsElevated(g_hwnd, hInstance))
dout << "Start with elevated permissions failed or declined by user" << std::endl;
//New process started (or not), exit current one
goto Cleanup;
}
InitCommonControls();
g_uiRegMsg = RegisterWindowMessage("DWI Trespasser FINDER");
hMutex = CreateMutex(NULL, FALSE, "DWI Trespasser MUTEX");
if (WaitForSingleObjectEx(hMutex, 1000, FALSE) == WAIT_TIMEOUT)
{
FindRunningApp(g_uiRegMsg);
return -1;
}
if ( !IsDisplayConfigurationValid( GetSystemBitDepth(g_hwnd), bGetD3D(), GetWindowModeActive()))
{
if (MsgDlg(g_hwnd,
MB_YESNOCANCEL | MB_SETFOREGROUND,
IDS_ERROR_TITLE,
IDS_ERR_INVALID_DISPLAY_CONFIGURATION) != IDYES)
goto Cleanup;
}
//
// Check To see if the installed registry flag is set. If it has not been
// set then we haven't been installed.
//
if (!GetRegValue(REG_KEY_INSTALLED, FALSE))
{
SetAllSettingsToDefault();
std::filesystem::path path = std::filesystem::current_path();
SetRegString(REG_KEY_DATA_DRIVE, path.string().c_str());
SetRegString(REG_KEY_INSTALLED_DIR, path.string().c_str());
}
// Check existance of file system
if (!TestDataDriveValidity())
goto Cleanup;
if (!ValidateDiskSpace(110))
{
ErrorDlg(g_hwnd, IDS_ERROR_DISKSPACE, 100);
goto Error;
}
//
// Display a dialog indicating that the application is running in safe
// mode if it is running in safe mode.
//
if (bSafemode() && !IsKeyDown(VK_SHIFT))
{
if (bRunSafeMode())
{
b_change_safemode = FALSE;
goto Cleanup;
}
}
if (!hPrevInstance)
{
if (!InitApplication(hInstance))
{
goto Error;
}
}
g_pMainWnd = new CMainWnd;
if (g_pMainWnd == NULL)
{
goto Error;
}
if (!InitInstance(hInstance, nCmdShow))
{
goto Error;
}
if (!g_hwnd)
{
goto Error;
}
DoRestartWithRenderDlg:
g_bRestartWithRenderDlg = FALSE;
bVideoCardChosen = false;
if (!bGetInitFlag() || IsKeyDown(VK_SHIFT))
{
pcdbMain.Clear();
g_CTPassGlobals.bHardReset = true;
CConfigureWnd dlg;
ForceShowCursor(TRUE);
dlg.MultiDialogBox(g_hInst, MAKEINTRESOURCE(IDD_INITIALIZATION), g_hwnd);
g_pMainWnd->m_bRelaunch = true;
bVideoCardChosen = true;
int windowWidth = 0;
int windowHeight = 0;
if (bGetDimensions(windowWidth, windowHeight))
{
SetWindowPos(g_hwnd, NULL, -1, -1, windowWidth, windowHeight,
SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
}
}
EnableMenuItem(GetSystemMenu(g_hwnd, FALSE),
SC_CLOSE,
MF_GRAYED);
EnableMenuItem(GetSystemMenu(g_hwnd, FALSE),
SC_MOVE,
MF_GRAYED);
// setup a global that contains the system page size.
SetupSystemPageSize();
//
// Create the audio system now we have a window handle
//
if (!CAudio::pcaAudio)
{
new CAudio(g_hwnd,
(bool)GetRegValue(REG_KEY_AUDIO_ENABLE, TRUE),
(bool)GetRegValue(REG_KEY_AUDIO_ENABLE3D, TRUE) & (!(bool)bSafeModeReg) );
}
RefreshAudioSettings();
// Initialize the global DirectDraw object.
i = g_initDD.Initialize();
if (i != 0)
{
switch (i)
{
case -1:
ErrorDlg(g_hwnd, IDS_ERROR_DDRAW_NOTFOUND);
goto Cleanup;
break;
case -2:
case -3:
case -4:
ErrorDlg(g_hwnd, IDS_ERROR_DDRAW_NOTFOUND);
goto Cleanup;
break;
}
}
//
// Check for Video Driver Certification
//
if (!g_initDD.IsCertified() &&
!GetRegValue(REG_KEY_DDRAW_CERT_IGNORE, FALSE))
{
CErrorDlg cdlg(ERRORDLG_DDRAW_CERTIFIED);
TraceError(("WinMain() -- "
"Video Card is not certified"));
if (cdlg.DoDialog() == IDCANCEL)
{
if (bVideoCardChosen)
{
bSetInitFlag(FALSE);
g_bRestartWithRenderDlg = true;
}
goto Cleanup;
}
}
//
// Check for Hardware Support
//
if (!g_initDD.IsHardwareSupported() &&
!GetRegValue(REG_KEY_DDRAW_HARD_IGNORE, FALSE))
{
CErrorDlg cdlg(ERRORDLG_DDRAW_HARDWARE);
TraceError(("WinMain() -- "
"Video Card does not have hardware support"));
if (cdlg.DoDialog() == IDCANCEL)
{
goto Cleanup;
}
}
Video::EnumerateDisplayModes();
//
// If safe mode is not active, set some defaults that depend on the CPU speed.
//
SetSpeedDefaults();
g_CTPassGlobals.SaveDefaultKeys();
g_CTPassGlobals.GetSavedKeys();
g_pMainWnd->m_bInit = true;
g_pMainWnd->InitSurface();
g_pMainWnd->StartGame();
iRet = 1;
Cleanup:
if (DirectDraw::pdd4)
{
DirectDraw::err = DirectDraw::pdd4->SetCooperativeLevel(g_hwnd, DDSCL_NORMAL);
}
// Release everything really well.
d3dDriver.Purge();
d3dDriver.Uninitialize();
if (pwWorld)
wWorld.Reset();
if (prasMainScreen)
{
prasMainScreen->uRefs = 1;
std::destroy_at(&prasMainScreen);
}
g_initDD.ReleaseAll();
// Remove the render shell.
delete prnshMain;
prnshMain = 0;
if (g_pMainWnd)
{
g_pMainWnd->m_bInit = false;
}
if (g_bRestartWithRenderDlg)
{
goto DoRestartWithRenderDlg;
}
if (g_hwnd)
{
DestroyWindow(g_hwnd);
g_hwnd = 0;
}
delete g_pMainWnd;
g_pMainWnd = NULL;
// Remove the audio, we are about to quit.
delete CAudio::pcaAudio;
CoUninitialize();
PostQuitMessage(0);
// BUGBUG: Close out file system
CloseKey(b_change_safemode);
return iRet;
Error:
iRet = 0;
goto Cleanup;
}
void DumpException(LPEXCEPTION_POINTERS pep_info)
{
if (!pep_info)
return;
// Open log with a timestamp.
time_t tm_timestamp;
time(&tm_timestamp);
FILE* pfile = fopen("error.log", "w");
if (!pfile)
return;
fprintf(pfile, "Trespasser Build: %ld, %ld, %ld\n", BUILD_MAJOR, BUILD_MINOR, BUILD_NUM);
fprintf(pfile, "Trespasser Fault: %s\n", ctime(&tm_timestamp));
// Print the exception record.
if (pep_info->ExceptionRecord)
{
fprintf(pfile, "Exception Record\n");
fprintf(pfile, "----------------\n");
fprintf(pfile, "Code : 0x%08X\n", pep_info->ExceptionRecord->ExceptionCode);
fprintf(pfile, "Flags : 0x%08X\n", pep_info->ExceptionRecord->ExceptionFlags);
fprintf(pfile, "Address: 0x%08p\n", pep_info->ExceptionRecord->ExceptionAddress);
for (uint u = 0; u < pep_info->ExceptionRecord->NumberParameters && u < 16; ++u)
fprintf(pfile, "Info %2ld: 0x%08X\n", u, pep_info->ExceptionRecord->ExceptionInformation[u]);
}
// Print the context record.
if (pep_info->ContextRecord)
{
fprintf(pfile, "\n");
fprintf(pfile, "Context Record\n");
fprintf(pfile, "--------------\n");
uint32* pu4 = (uint32*)pep_info->ContextRecord;
for (uint u = 0; u < sizeof(CONTEXT) / 4; ++u)
{
fprintf(pfile, "%2ld: 0x%08X", u, pu4[u]);
++u;
if (u >= sizeof(CONTEXT) / 4)
break;
fprintf(pfile, ", 0x%08X\n", pu4[u]);
}
}
// Close log.
fprintf(pfile, "\n");
fclose(pfile);
}
int FilterException(LPEXCEPTION_POINTERS ep_info)
{
Trace(("Exception:"));
Trace(("Exception Code: %x",ep_info->ExceptionRecord->ExceptionCode));
Trace(("Execution Address: %x",ep_info->ExceptionRecord->ExceptionAddress));
if (ep_info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
// Access violations have more info in the parameter section.
if (ep_info->ExceptionRecord->ExceptionInformation[0] == 0)
{
// illegal read
Trace(("Illegal Memory read from address %x",
ep_info->ExceptionRecord->ExceptionInformation[1]));
}
else
{
// illegal write
Trace(("Illegal Memory write to address %x",
ep_info->ExceptionRecord->ExceptionInformation[1]));
}
}
if (ep_info->ExceptionRecord->ExceptionFlags == 0)
{
Trace(("Excecution can be restarted..."));
}
else
{
// in this case do not return EXCEPTION_CONTINUE_EXECUTION
// otherwise you will get a EXCEPTION_NONCONTINUABLE_EXCEPTION.
Trace(("Excecution CANNOT be restarted"));
}
// Output the exception
DumpException(ep_info);
return EXCEPTION_EXECUTE_HANDLER;
}
//+--------------------------------------------------------------------------
//
// Function: WinMain
//
// Synopsis: Entry point function for this application
//
// Arguments: [hInstance] -- Instance handle for this application
// [hPrevInstance] -- previous instance handle
// [lpCmdLine] -- command line parameters
// [nCmdShow] -- how to display the window when created
//
// Returns: int -- Return from Quit Message
//
// History: 25-Sep-95 SHernd Created
//
//---------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int iRet;
#if BUILDVER_MODE == MODE_FINAL
__try
#endif
{
iRet = DoWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
#if BUILDVER_MODE == MODE_FINAL
__except (FilterException(GetExceptionInformation()))
{
__try
{
TrespassExceptionCleanup();
}
__except (FilterException(GetExceptionInformation()))
{
ExitProcess(0);
}
}
#endif
return iRet;
}
//+--------------------------------------------------------------------------
//
// Function: InitApplication
//
// Synopsis: Registers the window classes necessary for the application
// to run
//
// Arguments: [hInstance] -- instance that we are registering the classes
//
// Returns: BOOL -- TRUE -- if successful
// FALSE -- if NOT successful
//
// History: 10-Oct-95 SHernd Created
//
//---------------------------------------------------------------------------
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP));
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szAppName;
if (!::RegisterClass(&wc))
{
return FALSE;
}
return TRUE;
}
//+--------------------------------------------------------------------------
//
// Function: InitInstance
//
// Synopsis: Reads the application information and then creates the main
// window that is to be associated with this instance of the
// application
//
// Arguments: [hInstance] -- instance of the application
// [nCmdShow] -- how to show the window
//
// Returns: BOOL -- TRUE -- if successful
// FALSE -- if NOT successful
//
// History: 10-Oct-95 SHernd Created
//
//---------------------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
char sz[255];
g_hInst = hInstance;
LoadString(g_hInst, IDS_TITLE, sz, sizeof(sz));
g_hwnd = NULL;
int windowWidth = 640;
int windowHeight = 480;
bGetDimensions(windowWidth, windowHeight);
DWORD style = WS_VISIBLE | WS_POPUP | WS_SYSMENU;
if (GetWindowModeActive() == WindowMode::FRAMED)
style |= WS_OVERLAPPEDWINDOW;
if (!CreateWindowEx(0,
g_szAppName,
sz,
style,
0,
0,
windowWidth,
windowHeight,
NULL,
NULL,
hInstance,
NULL))
{
TraceError(("InitInstance() -- CreateWindow failed"));
return FALSE;
}
ShowWindow(g_hwnd, nCmdShow);
UpdateWindow(g_hwnd);
return TRUE;
}
//+--------------------------------------------------------------------------
//.
// Function: MsgDlg
//
// Synopsis: Actual warning/error handler.
//
// Arguments: [hwndParent] -- parent window handle
// [uiType] -- button types
// [uiCaption] -- caption string index
// [uiMsg] -- messge string index
// [...] -- variable argument list
//
// Returns: void
//
// History: 13-May-96 SHernd Created
//
//---------------------------------------------------------------------------
int __cdecl MsgDlg(HWND hwndParent,
UINT uiType,
UINT uiCaption,
UINT uiMsg,
...)
{
int iRet;
va_list vlShow;
va_start(vlShow, uiMsg);
iRet = ActualMsgDlg(hwndParent, uiType, uiCaption, uiMsg, vlShow);
va_end(vlShow);
return iRet;
}
int __cdecl ActualMsgDlg(HWND hwndParent,
UINT uiType,
UINT uiCaption,
UINT uiMsg,
va_list ap)
{
char szCaption[255];
char szMsg[4096];
char szResText[4096];
int iRet;
iRet = LoadString(g_hInst, uiCaption, szCaption, sizeof(szCaption));
if (iRet == 0)
{
return -1;
}
iRet = LoadString(g_hInst, uiMsg, szResText, sizeof(szResText));
if (iRet == 0)
{
return -1;
}
wvsprintf(szMsg, szResText, ap);
iRet = MessageBox(hwndParent,
szMsg,
szCaption,
MB_TOPMOST | MB_APPLMODAL | uiType);
return iRet;
}
//+--------------------------------------------------------------------------
//.
// Function: ErrorDlg
//
// Synopsis: Displays an error message. The error message is constructed
// from the String Resource Table number then using the passed
// in parameters it creates an error string. This error string
// is displayed as the text in the message box
//
// Arguments: [hwndParent] -- Parent Window
// [uiErrMsg] -- String Table Entry for error message base
//
// Returns: void
//
// History: 25-Apr-96 SHernd Created
//
//---------------------------------------------------------------------------
void __cdecl ErrorDlg(HWND hwndParent, UINT uiErrMsg, ...)
{
va_list vlShow;
va_start(vlShow, uiErrMsg);
ActualMsgDlg(hwndParent, MB_OK, IDS_ERROR_TITLE, uiErrMsg, vlShow);
va_end(vlShow);
}
// new allocator for audio.lib
#ifdef _DEBUG
void* __cdecl operator new(size_t nSize, const char* lpszFileName, int nLine)
{
return _malloc_dbg(nSize, _CLIENT_BLOCK, lpszFileName, nLine);
}
#endif
//+--------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
CErrorDlg::CErrorDlg(int iType)
{
m_iType = iType;
m_hwnd = NULL;
}
CErrorDlg::~CErrorDlg()
{
}
int CErrorDlg::DoDialog()
{
return DialogBoxParam(g_hInst,
MAKEINTRESOURCE(IDD_DXERROR),
NULL,
(DLGPROC)ErrorDlgProc,
(LPARAM)this);
}
BOOL CErrorDlg::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
char sz[1024];
int iIDS;
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
CenterWindow(hwnd, NULL);
// Load in Dialog Title
switch (m_iType)
{
case ERRORDLG_DSOUND:
iIDS = IDS_ERR_AUDIO_NOT_CERTIFIED;
break;
case ERRORDLG_DDRAW_CERTIFIED:
iIDS = IDS_ERR_VIDEO_NOT_CERTIFIED;
break;
case ERRORDLG_DDRAW_HARDWARE:
iIDS = IDS_ERR_VIDEO_NO_HARDWARE;
break;
}
LoadString(g_hInst, iIDS, sz, sizeof(sz));
SetWindowText(hwnd, sz);
// Load in Message Text
switch (m_iType)
{
case ERRORDLG_DSOUND:
iIDS = IDS_AUDIO_ERROR;
break;
case ERRORDLG_DDRAW_CERTIFIED:
iIDS = IDS_DISPLAY_ERROR;
break;
case ERRORDLG_DDRAW_HARDWARE:
iIDS = IDS_NOHARDWARE_ERROR;
break;
}
LoadString(g_hInst, iIDS, sz, sizeof(sz));
SetDlgItemText(hwnd, IDC_MESSAGE, sz);
return TRUE;
}
void CErrorDlg::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case IDOK:
if (IsDlgButtonChecked(hwnd, IDC_NODISPLAY) == BST_CHECKED)
{
switch (m_iType)
{
case ERRORDLG_DSOUND:
SetRegValue(REG_KEY_DSOUND_IGNORE, TRUE);
break;
case ERRORDLG_DDRAW_CERTIFIED:
SetRegValue(REG_KEY_DDRAW_CERT_IGNORE, TRUE);
break;
case ERRORDLG_DDRAW_HARDWARE:
SetRegValue(REG_KEY_DDRAW_HARD_IGNORE, TRUE);
break;
}
}
case IDCANCEL:
EndDialog(hwnd, id);
break;
}
}
void CErrorDlg::OnDestroy(HWND hwnd)
{
}
BOOL CALLBACK ErrorDlgProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
CErrorDlg * pwnd = (CErrorDlg*)GetProp(hwnd, "ClassWindowName");
if (pwnd == NULL)
{
if (uiMsg == WM_INITDIALOG)
{
pwnd = (CErrorDlg *)lParam;
SetProp(hwnd, "ClassWindowName", pwnd);
if (pwnd == NULL)
{
return TRUE;
}
pwnd->m_hwnd = hwnd;
}
else
{
return FALSE;
}
}
switch (uiMsg)
{
HANDLE_MSG(hwnd, WM_COMMAND, pwnd->OnCommand);
HANDLE_MSG(hwnd, WM_DESTROY, pwnd->OnDestroy);
HANDLE_MSG(hwnd, WM_INITDIALOG, pwnd->OnInitDialog);
}
return FALSE;
}
//*********************************************************************************************
uint32 u4LookupResourceString(int32 i4_id,char* str_buf,uint32 u4_buf_len)
{
char buf[1024];
int i_res = LoadString(g_hInst, IDS_STR_HINTS + i4_id, buf, 1024);
if ((i_res>0) && (i_res<(int)u4_buf_len))
{
// copy the string to the destination buffer and process and escape sequences
wsprintf(str_buf,buf);
Assert(strlen(str_buf)<u4_buf_len);
return strlen(str_buf);
}
return 0;
}