/*
* $Id$
*
* (C) 2003-2006 Gabest
* (C) 2006-2011 see AUTHORS
*
* This file is part of mplayerc.
*
* Mplayerc is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Mplayerc is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "stdafx.h"
#include "mplayerc.h"
#include
#include "MainFrm.h"
#include "../../DSUtil/DSUtil.h"
#include "Struct.h"
#include "FileVersionInfo.h"
#include
#include "Ifo.h"
#include "Monitors.h"
#include "..\..\..\include\Version.h"
extern "C" {
int mingw_app_type = 1;
}
void CorrectComboListWidth(CComboBox& box, CFont* pWndFont)
{
int cnt = box.GetCount();
if(cnt <= 0) {
return;
}
CDC* pDC = box.GetDC();
pDC->SelectObject(pWndFont);
int maxw = box.GetDroppedWidth();
for(int i = 0; i < cnt; i++) {
CString str;
box.GetLBText(i, str);
int w = pDC->GetTextExtent(str).cx + 22;
if(maxw < w) {
maxw = w;
}
}
box.ReleaseDC(pDC);
box.SetDroppedWidth(maxw);
}
HICON LoadIcon(CString fn, bool fSmall)
{
if(fn.IsEmpty()) {
return(NULL);
}
CString ext = fn.Left(fn.Find(_T("://"))+1).TrimRight(':');
if(ext.IsEmpty() || !ext.CompareNoCase(_T("file"))) {
ext = _T(".") + fn.Mid(fn.ReverseFind('.')+1);
}
CSize size(fSmall?16:32,fSmall?16:32);
if(!ext.CompareNoCase(_T(".ifo"))) {
if(HICON hIcon = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_DVD), IMAGE_ICON, size.cx, size.cy, 0)) {
return(hIcon);
}
}
if(!ext.CompareNoCase(_T(".cda"))) {
if(HICON hIcon = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_AUDIOCD), IMAGE_ICON, size.cx, size.cy, 0)) {
return(hIcon);
}
}
do {
CRegKey key;
TCHAR buff[256];
ULONG len;
if(ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, ext + _T("\\DefaultIcon"), KEY_READ)) {
if(ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, ext, KEY_READ)) {
break;
}
len = sizeof(buff)/sizeof(buff[0]);
memset(buff, 0, sizeof(buff));
if(ERROR_SUCCESS != key.QueryStringValue(NULL, buff, &len) || (ext = buff).Trim().IsEmpty()) {
break;
}
if(ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, ext + _T("\\DefaultIcon"), KEY_READ)) {
break;
}
}
CString icon;
len = sizeof(buff)/sizeof(buff[0]);
memset(buff, 0, sizeof(buff));
if(ERROR_SUCCESS != key.QueryStringValue(NULL, buff, &len) || (icon = buff).Trim().IsEmpty()) {
break;
}
int i = icon.ReverseFind(',');
if(i < 0) {
break;
}
int id = 0;
if(_stscanf_s(icon.Mid(i+1), _T("%d"), &id) != 1) {
break;
}
icon = icon.Left(i);
HICON hIcon = NULL;
UINT cnt = fSmall
? ExtractIconEx(icon, id, NULL, &hIcon, 1)
: ExtractIconEx(icon, id, &hIcon, NULL, 1);
UNUSED_ALWAYS(cnt);
if(hIcon) {
return hIcon;
}
} while(0);
return((HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_UNKNOWN), IMAGE_ICON, size.cx, size.cy, 0));
}
bool LoadType(CString fn, CString& type)
{
CRegKey key;
TCHAR buff[256];
ULONG len;
if(fn.IsEmpty()) {
return(NULL);
}
CString ext = fn.Left(fn.Find(_T("://"))+1).TrimRight(':');
if(ext.IsEmpty() || !ext.CompareNoCase(_T("file"))) {
ext = _T(".") + fn.Mid(fn.ReverseFind('.')+1);
}
CString tmp = _T("");
CString mplayerc_ext = _T("mplayerc") + ext;
if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, mplayerc_ext)) {
tmp = mplayerc_ext;
}
if((tmp == _T("")) && (ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, ext))) {
return(false);
}
if(tmp == _T("")) {
tmp = ext;
}
while(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, tmp)) {
len = sizeof(buff)/sizeof(buff[0]);
memset(buff, 0, sizeof(buff));
if(ERROR_SUCCESS != key.QueryStringValue(NULL, buff, &len)) {
break;
}
CString str(buff);
str.Trim();
if(str.IsEmpty() || str == tmp) {
break;
}
tmp = str;
}
type = tmp;
return(true);
}
bool LoadResource(UINT resid, CStringA& str, LPCTSTR restype)
{
str.Empty();
HRSRC hrsrc = FindResource(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(resid), restype);
if(!hrsrc) {
return(false);
}
HGLOBAL hGlobal = LoadResource(AfxGetApp()->m_hInstance, hrsrc);
if(!hGlobal) {
return(false);
}
DWORD size = SizeofResource(AfxGetApp()->m_hInstance, hrsrc);
if(!size) {
return(false);
}
memcpy(str.GetBufferSetLength(size), LockResource(hGlobal), size);
return(true);
}
WORD assignedToCmd(UINT keyOrMouseValue, bool bCheckMouse) {
WORD assignTo = 0;
AppSettings& s = AfxGetAppSettings();
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos && (!assignTo)) {
wmcmd& wc = s.wmcmds.GetNext(pos);
if(bCheckMouse) {
if(wc.mouse == keyOrMouseValue) {
assignTo = wc.cmd;
break;
}
} else {
if(wc.key == keyOrMouseValue) {
assignTo = wc.cmd;
break;
}
}
}
return assignTo;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
extern "C" char *GetFFmpegCompiler();
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
// No message handlers
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog() {
USES_CONVERSION;
UpdateData();
#ifdef _WIN64
m_appname += _T(" x64");
#endif
m_strBuildNumber = AfxGetMyApp()->m_strVersion;
#if defined(__INTEL_COMPILER)
#if (__INTEL_COMPILER >= 1200)
m_MPCCompiler = _T("ICL 12.x");
#elif (__INTEL_COMPILER >= 1100)
m_MPCCompiler = _T("ICL 11.x");
#elif (__INTEL_COMPILER >= 1000)
m_MPCCompiler = _T("ICL 10.x");
#else
#error Compiler is not supported!
#endif
#elif defined(_MSC_VER)
#if (_MSC_VER == 1600)
#if (_MSC_FULL_VER >= 160040219)
m_MPCCompiler = _T("MSVC 2010 SP1");
#else
m_MPCCompiler = _T("MSVC 2010");
#endif
#elif (_MSC_VER == 1500)
#if (_MSC_FULL_VER >= 150030729)
m_MPCCompiler = _T("MSVC 2008 SP1");
#else
m_MPCCompiler = _T("MSVC 2008");
#endif
#elif (_MSC_VER < 1500)
#error Compiler is not supported!
#endif
// Note: /arch:SSE and /arch:SSE2 are only available when you compile for the x86 platform.
// Link: http://msdn.microsoft.com/en-us/library/7t5yh4fd.aspx
// Link: http://msdn.microsoft.com/en-us/library/b0084kay.aspx
#if !defined(_M_X64) && defined(_M_IX86_FP)
//#if (_M_IX86_FP == 0) // 0 if /arch was not used.
// m_MPCCompiler += _T("");
#if (_M_IX86_FP == 1) // 1 if /arch:SSE was used.
m_MPCCompiler += _T(" (SSE)");
#elif (_M_IX86_FP == 2) // 2 if /arch:SSE2 was used.
m_MPCCompiler += _T(" (SSE2)");
#endif
#endif // _M_IX86_FP
#ifdef _DEBUG
m_MPCCompiler += _T(" Debug");
#endif
#else
#error Please add support for your compiler
#endif
#if HAS_FFMPEG
m_FFmpegCompiler.Format (A2W(GetFFmpegCompiler()));
#endif
UpdateData(FALSE);
return TRUE;
}
CString m_appname;
CString m_strBuildNumber;
CString m_MPCCompiler;
CString m_FFmpegCompiler;
afx_msg void OnHomepage(NMHDR *pNMHDR, LRESULT *pResult);
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD), m_appname(_T(""))
, m_strBuildNumber(_T(""))
, m_MPCCompiler(_T(""))
, m_FFmpegCompiler(_T(""))
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
DDX_Text(pDX, IDC_STATIC1, m_appname);
DDX_Text(pDX, IDC_BUILD_NUMBER, m_strBuildNumber);
DDX_Text(pDX, IDC_MPC_COMPILER, m_MPCCompiler);
DDX_Text(pDX, IDC_FFMPEG_COMPILER, m_FFmpegCompiler);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
ON_NOTIFY(NM_CLICK, IDC_SOURCEFORGE_LINK, &CAboutDlg::OnHomepage)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMPlayerCApp
BEGIN_MESSAGE_MAP(CMPlayerCApp, CWinApp)
//{{AFX_MSG_MAP(CMPlayerCApp)
ON_COMMAND(ID_HELP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_EXIT, OnFileExit)
//}}AFX_MSG_MAP
ON_COMMAND(ID_HELP_SHOWCOMMANDLINESWITCHES, OnHelpShowcommandlineswitches)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMPlayerCApp construction
CMPlayerCApp::CMPlayerCApp()
// : m_hMutexOneInstance(NULL)
{
CFileVersionInfo Version;
TCHAR strApp [_MAX_PATH];
GetModuleFileNameEx (GetCurrentProcess(), AfxGetMyApp()->m_hInstance, strApp, _MAX_PATH);
Version.Create (strApp);
m_strVersion = Version.GetFileVersionEx();
memset (&m_ColorControl, 0, sizeof(m_ColorControl));
m_ColorControl[0].dwSize = sizeof (COLORPROPERTY_RANGE);
m_ColorControl[0].dwProperty = Brightness;
m_ColorControl[1].dwSize = sizeof (COLORPROPERTY_RANGE);
m_ColorControl[1].dwProperty = Contrast;
m_ColorControl[2].dwSize = sizeof (COLORPROPERTY_RANGE);
m_ColorControl[2].dwProperty = Hue;
m_ColorControl[3].dwSize = sizeof (COLORPROPERTY_RANGE);
m_ColorControl[3].dwProperty = Saturation;
GetRemoteControlCode = GetRemoteControlCodeMicrosoft;
}
void CMPlayerCApp::ShowCmdlnSwitches() const
{
CString s;
if(m_s.nCLSwitches&CLSW_UNRECOGNIZEDSWITCH) {
CAtlList sl;
for(int i = 0; i < __argc; i++) {
sl.AddTail(__targv[i]);
}
s += ResStr(IDS_UNKNOWN_SWITCH) + Implode(sl, ' ') + _T("\n\n");
}
s += ResStr (IDS_USAGE);
AfxMessageBox(s);
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CMPlayerCApp object
CMPlayerCApp theApp;
HWND g_hWnd = NULL;
bool CMPlayerCApp::StoreSettingsToIni()
{
CString ini = GetIniPath();
/*
FILE* f;
if(!(f = _tfopen(ini, _T("r+"))) && !(f = _tfopen(ini, _T("w"))))
return StoreSettingsToRegistry();
fclose(f);
*/
free((void*)m_pszRegistryKey);
m_pszRegistryKey = NULL;
free((void*)m_pszProfileName);
m_pszProfileName = _tcsdup(ini);
// We can only use UTF16-LE for unicode ini files in windows. UTF8/UTF16-BE do not work.
// So to ensure we have correct encoding for ini files, create a file with right BOM first,
// then add some comments in first line to make sure it's not empty.
// If you want to try unicode ini, uncomment following code block.
/*
if(!::PathFileExists(m_pszProfileName)) // don't overwrite existing ini file
{
LPTSTR pszComments = _T("; Media Player Classic - Home Cinema");
WORD wBOM = 0xFEFF;// UTF16-LE BOM(FFFE)
DWORD nBytes;
HANDLE hFile = ::CreateFile(m_pszProfileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
::WriteFile(hFile, &wBOM, sizeof(WORD), &nBytes, NULL);
::WriteFile(hFile, pszComments, (_tcslen(pszComments)+1)*(sizeof(TCHAR)), &nBytes, NULL);
::CloseHandle(hFile);
}
}
*/
return(true);
}
bool CMPlayerCApp::StoreSettingsToRegistry()
{
_tremove(GetIniPath());
free((void*)m_pszRegistryKey);
m_pszRegistryKey = NULL;
SetRegistryKey(_T("Gabest"));
return(true);
}
CString CMPlayerCApp::GetIniPath() const
{
CString path;
GetModuleFileName(AfxGetInstanceHandle(), path.GetBuffer(_MAX_PATH), _MAX_PATH);
path.ReleaseBuffer();
path = path.Left(path.ReverseFind('.')+1) + _T("ini");
return(path);
}
bool CMPlayerCApp::IsIniValid() const
{
CFileStatus fs;
return CFileGetStatus(GetIniPath(), fs) && fs.m_size > 0;
}
bool CMPlayerCApp::GetAppSavePath(CString& path)
{
path.Empty();
if(IsIniValid()) { // If settings ini file found, store stuff in the same folder as the exe file
GetModuleFileName(AfxGetInstanceHandle(), path.GetBuffer(_MAX_PATH), _MAX_PATH);
path.ReleaseBuffer();
path = path.Left(path.ReverseFind('\\'));
} else {
CRegKey key;
if(ERROR_SUCCESS == key.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"), KEY_READ)) {
ULONG len = _MAX_PATH;
if(ERROR_SUCCESS == key.QueryStringValue(_T("AppData"), path.GetBuffer(_MAX_PATH), &len)) {
path.ReleaseBufferSetLength(len);
}
}
if(path.IsEmpty()) {
return(false);
}
CPath p;
p.Combine(path, _T("Media Player Classic"));
path = (LPCTSTR)p;
}
return(true);
}
void CMPlayerCApp::PreProcessCommandLine()
{
m_cmdln.RemoveAll();
for(int i = 1; i < __argc; i++) {
CString str = CString(__targv[i]).Trim(_T(" \""));
if(str[0] != '/' && str[0] != '-' && str.Find(_T(":")) < 0) {
LPTSTR p = NULL;
CString str2;
str2.ReleaseBuffer(GetFullPathName(str, _MAX_PATH, str2.GetBuffer(_MAX_PATH), &p));
CFileStatus fs;
if(!str2.IsEmpty() && CFileGetStatus(str2, fs)) {
str = str2;
}
}
m_cmdln.AddTail(str);
}
}
void CMPlayerCApp::SendCommandLine(HWND hWnd)
{
if(m_cmdln.IsEmpty()) {
return;
}
int bufflen = sizeof(DWORD);
POSITION pos = m_cmdln.GetHeadPosition();
while(pos) {
bufflen += (m_cmdln.GetNext(pos).GetLength()+1)*sizeof(TCHAR);
}
CAutoVectorPtr buff;
if(!buff.Allocate(bufflen)) {
return;
}
BYTE* p = buff;
*(DWORD*)p = m_cmdln.GetCount();
p += sizeof(DWORD);
pos = m_cmdln.GetHeadPosition();
while(pos) {
CString s = m_cmdln.GetNext(pos);
int len = (s.GetLength()+1)*sizeof(TCHAR);
memcpy(p, s, len);
p += len;
}
COPYDATASTRUCT cds;
cds.dwData = 0x6ABE51;
cds.cbData = bufflen;
cds.lpData = (void*)(BYTE*)buff;
SendMessage(hWnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
}
/////////////////////////////////////////////////////////////////////////////
// CMPlayerCApp initialization
#include
#include
BOOL (__stdcall * Real_IsDebuggerPresent)(void)
= IsDebuggerPresent;
LONG (__stdcall * Real_ChangeDisplaySettingsExA)(LPCSTR a0,
LPDEVMODEA a1,
HWND a2,
DWORD a3,
LPVOID a4)
= ChangeDisplaySettingsExA;
LONG (__stdcall * Real_ChangeDisplaySettingsExW)(LPCWSTR a0,
LPDEVMODEW a1,
HWND a2,
DWORD a3,
LPVOID a4)
= ChangeDisplaySettingsExW;
HANDLE (__stdcall * Real_CreateFileA)(LPCSTR a0,
DWORD a1,
DWORD a2,
LPSECURITY_ATTRIBUTES a3,
DWORD a4,
DWORD a5,
HANDLE a6)
= CreateFileA;
HANDLE (__stdcall * Real_CreateFileW)(LPCWSTR a0,
DWORD a1,
DWORD a2,
LPSECURITY_ATTRIBUTES a3,
DWORD a4,
DWORD a5,
HANDLE a6)
= CreateFileW;
BOOL (__stdcall * Real_DeviceIoControl)(HANDLE a0,
DWORD a1,
LPVOID a2,
DWORD a3,
LPVOID a4,
DWORD a5,
LPDWORD a6,
LPOVERLAPPED a7)
= DeviceIoControl;
MMRESULT (__stdcall * Real_mixerSetControlDetails)( HMIXEROBJ hmxobj,
LPMIXERCONTROLDETAILS pmxcd,
DWORD fdwDetails)
= mixerSetControlDetails;
typedef NTSTATUS (WINAPI *FUNC_NTQUERYINFORMATIONPROCESS)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
static FUNC_NTQUERYINFORMATIONPROCESS Real_NtQueryInformationProcess = NULL;
/*
NTSTATUS (* Real_NtQueryInformationProcess) (HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength)
= NULL;
*/
BOOL WINAPI Mine_IsDebuggerPresent()
{
TRACE(_T("Oops, somebody was trying to be naughty! (called IsDebuggerPresent)\n"));
return FALSE;
}
NTSTATUS WINAPI Mine_NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength)
{
NTSTATUS nRet;
nRet = Real_NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength);
if (ProcessInformationClass == ProcessBasicInformation) {
PROCESS_BASIC_INFORMATION* pbi = (PROCESS_BASIC_INFORMATION*)ProcessInformation;
PEB_NT* pPEB;
PEB_NT PEB;
pPEB = (PEB_NT*)pbi->PebBaseAddress;
ReadProcessMemory(ProcessHandle, pPEB, &PEB, sizeof(PEB), NULL);
PEB.BeingDebugged = 0;
WriteProcessMemory(ProcessHandle, pPEB, &PEB, sizeof(PEB), NULL);
} else if (ProcessInformationClass == 7) { // ProcessDebugPort
BOOL* pDebugPort = (BOOL*)ProcessInformation;
*pDebugPort = FALSE;
}
return nRet;
}
LONG WINAPI Mine_ChangeDisplaySettingsEx(LONG ret, DWORD dwFlags, LPVOID lParam)
{
if(dwFlags&CDS_VIDEOPARAMETERS) {
VIDEOPARAMETERS* vp = (VIDEOPARAMETERS*)lParam;
if(vp->Guid == GUIDFromCString(_T("{02C62061-1097-11d1-920F-00A024DF156E}"))
&& (vp->dwFlags&VP_FLAGS_COPYPROTECT)) {
if(vp->dwCommand == VP_COMMAND_GET) {
if((vp->dwTVStandard&VP_TV_STANDARD_WIN_VGA)
&& vp->dwTVStandard != VP_TV_STANDARD_WIN_VGA) {
TRACE(_T("Ooops, tv-out enabled? macrovision checks suck..."));
vp->dwTVStandard = VP_TV_STANDARD_WIN_VGA;
}
} else if(vp->dwCommand == VP_COMMAND_SET) {
TRACE(_T("Ooops, as I already told ya, no need for any macrovision bs here"));
return 0;
}
}
}
return ret;
}
LONG WINAPI Mine_ChangeDisplaySettingsExA(LPCSTR lpszDeviceName, LPDEVMODEA lpDevMode, HWND hwnd, DWORD dwFlags, LPVOID lParam)
{
return Mine_ChangeDisplaySettingsEx(
Real_ChangeDisplaySettingsExA(lpszDeviceName, lpDevMode, hwnd, dwFlags, lParam),
dwFlags,
lParam);
}
LONG WINAPI Mine_ChangeDisplaySettingsExW(LPCWSTR lpszDeviceName, LPDEVMODEW lpDevMode, HWND hwnd, DWORD dwFlags, LPVOID lParam)
{
return Mine_ChangeDisplaySettingsEx(
Real_ChangeDisplaySettingsExW(lpszDeviceName, lpDevMode, hwnd, dwFlags, lParam),
dwFlags,
lParam);
}
HANDLE WINAPI Mine_CreateFileA(LPCSTR p1, DWORD p2, DWORD p3, LPSECURITY_ATTRIBUTES p4, DWORD p5, DWORD p6, HANDLE p7)
{
//CStringA fn(p1);
//fn.MakeLower();
//int i = fn.Find(".part");
//if(i > 0 && i == fn.GetLength() - 5)
p3 |= FILE_SHARE_WRITE;
return Real_CreateFileA(p1, p2, p3, p4, p5, p6, p7);
}
BOOL CreateFakeVideoTS(LPCWSTR strIFOPath, LPWSTR strFakeFile, size_t nFakeFileSize)
{
BOOL bRet = FALSE;
WCHAR szTempPath[_MAX_PATH];
WCHAR strFileName[_MAX_PATH];
WCHAR strExt[_MAX_EXT];
CIfo Ifo;
if (!GetTempPathW(_MAX_PATH, szTempPath)) {
return FALSE;
}
_wsplitpath_s (strIFOPath, NULL, 0, NULL, 0, strFileName, countof(strFileName), strExt, countof(strExt));
_snwprintf_s (strFakeFile, nFakeFileSize, _TRUNCATE, L"%sMPC%s%s", szTempPath, strFileName, strExt);
if (Ifo.OpenFile (strIFOPath) &&
Ifo.RemoveUOPs() &&
Ifo.SaveFile (strFakeFile)) {
bRet = TRUE;
}
return bRet;
}
HANDLE WINAPI Mine_CreateFileW(LPCWSTR p1, DWORD p2, DWORD p3, LPSECURITY_ATTRIBUTES p4, DWORD p5, DWORD p6, HANDLE p7)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
WCHAR strFakeFile[_MAX_PATH];
int nLen = wcslen(p1);
p3 |= FILE_SHARE_WRITE;
if (nLen>=4 && _wcsicmp (p1 + nLen-4, L".ifo") == 0) {
if (CreateFakeVideoTS(p1, strFakeFile, countof(strFakeFile))) {
hFile = Real_CreateFileW(strFakeFile, p2, p3, p4, p5, p6, p7);
}
}
if (hFile == INVALID_HANDLE_VALUE) {
hFile = Real_CreateFileW(p1, p2, p3, p4, p5, p6, p7);
}
return hFile;
}
MMRESULT WINAPI Mine_mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails)
{
if(fdwDetails == (MIXER_OBJECTF_HMIXER|MIXER_SETCONTROLDETAILSF_VALUE)) {
return MMSYSERR_NOERROR; // don't touch the mixer, kthx
}
return Real_mixerSetControlDetails(hmxobj, pmxcd, fdwDetails);
}
BOOL WINAPI Mine_DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
{
BOOL ret = Real_DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
if(IOCTL_DVD_GET_REGION == dwIoControlCode && lpOutBuffer
&& lpBytesReturned && *lpBytesReturned == sizeof(DVD_REGION)) {
DVD_REGION* pDVDRegion = (DVD_REGION*)lpOutBuffer;
pDVDRegion->SystemRegion = ~pDVDRegion->RegionData;
}
return ret;
}
// Class ssftest is nowhere to see except here. Right now remove it from release build, should we just remove it completely?
#ifdef _DEBUG
#include "../../Subtitles/SSF.h"
#include "../../Subtitles/RTS.h"
#include "../../SubPic/MemSubPic.h"
class ssftest
{
public:
ssftest() {
Sleep(10000);
MessageBeep((UINT)-1);
// 8; //
SubPicDesc spd;
spd.w = 640;
spd.h = 480;
spd.bpp = 32;
spd.pitch = spd.w*spd.bpp>>3;
spd.type = MSP_RGB32;
spd.vidrect = CRect(0, 0, spd.w, spd.h);
spd.bits = DNew BYTE[spd.pitch*spd.h];
CCritSec csLock;
/*
CRenderedTextSubtitle s(&csLock);
s.Open(_T("../../Subtitles/libssf/demo/demo.ssa"), 1);
for(int i = 2*60*1000+2000; i < 2*60*1000+17000; i += 10)
{
memsetd(spd.bits, 0xff000000, spd.pitch*spd.h);
CRect bbox;
bbox.SetRectEmpty();
s.Render(spd, 10000i64*i, 25, bbox);
}
*/
try {
ssf::CRenderer s(&csLock);
s.Open(_T("../../Subtitles/libssf/demo/demo.ssf"));
for(int i = 2*60*1000+2000; i < 2*60*1000+17000; i += 40)
//for(int i = 2*60*1000+2000; i < 2*60*1000+17000; i += 1000)
//for(int i = 0; i < 5000; i += 40)
{
memsetd(spd.bits, 0xff000000, spd.pitch*spd.h);
CRect bbox;
bbox.SetRectEmpty();
s.Render(spd, 10000i64*i, 25, bbox);
}
} catch(ssf::Exception& e) {
UNREFERENCED_PARAMETER(e);
TRACE(_T("%s\n"), e.ToString());
ASSERT(0);
}
delete [] spd.bits;
::ExitProcess(0);
}
};
#endif
BOOL SetHeapOptions()
{
HMODULE hLib = LoadLibrary(L"kernel32.dll");
if (hLib == NULL) {
return FALSE;
}
typedef BOOL (WINAPI *HSI)
(HANDLE, HEAP_INFORMATION_CLASS ,PVOID, SIZE_T);
HSI pHsi = (HSI)GetProcAddress(hLib,"HeapSetInformation");
if (!pHsi) {
FreeLibrary(hLib);
return FALSE;
}
#ifndef HeapEnableTerminationOnCorruption
# define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
#endif
BOOL fRet = (pHsi)(NULL,HeapEnableTerminationOnCorruption,NULL,0)
? TRUE
: FALSE;
if (hLib) {
FreeLibrary(hLib);
}
return fRet;
}
BOOL CMPlayerCApp::InitInstance()
{
// Remove the working directory from the search path to work around the DLL preloading vulnerability
SetDllDirectory(_T(""));
long lError;
#ifdef GOTHTRACE
// Used for tracing when debugger can't be used, e.g. when using some commercial decoders
// Print traces usint _tprintf()
if (AllocConsole()) {
FILE * foo; // Not used
freopen_s(&foo, "conin$", "r", stdin); // Redirect stdin etc. to console
freopen_s(&foo, "conout$", "w", stdout);
freopen_s(&foo, "conout$", "w", stderr);
} else {
AfxMessageBox(_T("Could not create console"));
}
#endif
if(SetHeapOptions()) {
TRACE(_T("Terminate on corruption enabled\n"));
} else {
CString heap_err;
heap_err.Format(_T("Terminate on corruption error = %d\n"), GetLastError());
TRACE(heap_err);
}
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Real_IsDebuggerPresent, (PVOID)Mine_IsDebuggerPresent);
DetourAttach(&(PVOID&)Real_ChangeDisplaySettingsExA, (PVOID)Mine_ChangeDisplaySettingsExA);
DetourAttach(&(PVOID&)Real_ChangeDisplaySettingsExW, (PVOID)Mine_ChangeDisplaySettingsExW);
DetourAttach(&(PVOID&)Real_CreateFileA, (PVOID)Mine_CreateFileA);
DetourAttach(&(PVOID&)Real_CreateFileW, (PVOID)Mine_CreateFileW);
DetourAttach(&(PVOID&)Real_mixerSetControlDetails, (PVOID)Mine_mixerSetControlDetails);
DetourAttach(&(PVOID&)Real_DeviceIoControl, (PVOID)Mine_DeviceIoControl);
HMODULE hNTDLL = LoadLibrary (_T("ntdll.dll"));
UNUSED_ALWAYS(hNTDLL);
#ifndef _DEBUG // Disable NtQueryInformationProcess in debug (prevent VS debugger to stop on crash address)
if (hNTDLL) {
Real_NtQueryInformationProcess = (FUNC_NTQUERYINFORMATIONPROCESS)GetProcAddress (hNTDLL, "NtQueryInformationProcess");
if (Real_NtQueryInformationProcess) {
DetourAttach(&(PVOID&)Real_NtQueryInformationProcess, (PVOID)Mine_NtQueryInformationProcess);
}
}
#endif
CFilterMapper2::Init();
lError = DetourTransactionCommit();
ASSERT (lError == NOERROR);
HRESULT hr;
if(FAILED(hr = OleInitialize(0))) {
AfxMessageBox(_T("OleInitialize failed!"));
return FALSE;
}
WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS));
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = LoadIcon(IDR_MAINFRAME);
wndcls.hCursor = LoadCursor(IDC_ARROW);
wndcls.hbrBackground = 0;//(HBRUSH)(COLOR_WINDOW + 1); // no bkg brush, the view and the bars should always fill the whole client area
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = MPC_WND_CLASS_NAME;
if(!AfxRegisterClass(&wndcls)) {
AfxMessageBox(_T("MainFrm class registration failed!"));
return FALSE;
}
if(!AfxSocketInit(NULL)) {
AfxMessageBox(_T("AfxSocketInit failed!"));
return FALSE;
}
PreProcessCommandLine();
if(IsIniValid()) {
StoreSettingsToIni();
} else {
StoreSettingsToRegistry();
}
m_s.ParseCommandLine(m_cmdln);
if(m_s.nCLSwitches&(CLSW_HELP|CLSW_UNRECOGNIZEDSWITCH)) {
m_s.UpdateData(false);
ShowCmdlnSwitches();
return FALSE;
}
if((m_s.nCLSwitches&CLSW_CLOSE) && m_s.slFiles.IsEmpty()) {
return FALSE;
}
m_s.UpdateData(false);
if((m_s.nCLSwitches&CLSW_REGEXTVID) || (m_s.nCLSwitches&CLSW_REGEXTAUD)) {
CMediaFormats& mf = m_s.m_Formats;
for(int i = 0; i < (int)mf.GetCount(); i++) {
if(!mf[i].GetLabel().CompareNoCase(ResStr(IDS_AG_PLAYLIST_FILE))) {
continue;
}
bool fAudioOnly = mf[i].IsAudioOnly();
int j = 0;
CString str = mf[i].GetExtsWithPeriod();
for(CString ext = str.Tokenize(_T(" "), j); !ext.IsEmpty(); ext = str.Tokenize(_T(" "), j)) {
if(((m_s.nCLSwitches&CLSW_REGEXTVID) && !fAudioOnly) || ((m_s.nCLSwitches&CLSW_REGEXTAUD) && fAudioOnly)) {
CPPageFormats::RegisterExt(ext, mf[i].GetLabel(), true);
}
}
}
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return FALSE;
}
if((m_s.nCLSwitches&CLSW_UNREGEXT)) {
CMediaFormats& mf = m_s.m_Formats;
for(int i = 0; i < (int)mf.GetCount(); i++) {
int j = 0;
CString str = mf[i].GetExtsWithPeriod();
for(CString ext = str.Tokenize(_T(" "), j); !ext.IsEmpty(); ext = str.Tokenize(_T(" "), j)) {
CPPageFormats::RegisterExt(ext, mf[i].GetLabel(), false);
}
}
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return FALSE;
}
// Enable to open options with administrator privilege (for Vista UAC)
if (m_s.nCLSwitches & CLSW_ADMINOPTION) {
switch (m_s.iAdminOption) {
case CPPageFormats::IDD : {
CPPageSheet options(ResStr(IDS_OPTIONS_CAPTION), NULL, NULL, m_s.iAdminOption);
options.LockPage();
options.DoModal();
}
break;
default :
ASSERT (FALSE);
}
return FALSE;
}
m_mutexOneInstance.Create(NULL, TRUE, MPC_WND_CLASS_NAME);
if(GetLastError() == ERROR_ALREADY_EXISTS
&& (!(m_s.fAllowMultipleInst || (m_s.nCLSwitches&CLSW_NEW) || m_cmdln.IsEmpty())
|| (m_s.nCLSwitches&CLSW_ADD))) {
int wait_count = 0;
HWND hWnd = ::FindWindow(MPC_WND_CLASS_NAME, NULL);
while(!hWnd && (wait_count++<200)) {
Sleep(100);
hWnd = ::FindWindow(MPC_WND_CLASS_NAME, NULL);
}
if(hWnd && (wait_count<200)) {
SetForegroundWindow(hWnd);
if(!(m_s.nCLSwitches&CLSW_MINIMIZED) && IsIconic(hWnd)) {
ShowWindow(hWnd, SW_RESTORE);
}
SendCommandLine(hWnd);
return FALSE;
}
}
AfxGetMyApp()->m_AudioRendererDisplayName_CL = _T("");
if(!__super::InitInstance()) {
AfxMessageBox(_T("InitInstance failed!"));
return FALSE;
}
CRegKey key;
if(ERROR_SUCCESS == key.Create(HKEY_LOCAL_MACHINE, _T("Software\\Gabest\\Media Player Classic"))) {
CString path;
GetModuleFileName(AfxGetInstanceHandle(), path.GetBuffer(_MAX_PATH), _MAX_PATH);
path.ReleaseBuffer();
key.SetStringValue(_T("ExePath"), path);
}
AfxEnableControlContainer();
CMainFrame* pFrame = DNew CMainFrame;
m_pMainWnd = pFrame;
if ( !pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, NULL, NULL) ) {
AfxMessageBox(_T("CMainFrame::LoadFrame failed!"));
return FALSE;
}
pFrame->SetDefaultWindowRect((m_s.nCLSwitches&CLSW_MONITOR)?m_s.iMonitor:0);
pFrame->RestoreFloatingControlBars();
pFrame->SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE);
pFrame->DragAcceptFiles();
pFrame->ShowWindow((m_s.nCLSwitches&CLSW_MINIMIZED)?SW_SHOWMINIMIZED:SW_SHOW);
pFrame->UpdateWindow();
pFrame->m_hAccelTable = m_s.hAccel;
m_s.WinLircClient.SetHWND(m_pMainWnd->m_hWnd);
if(m_s.fWinLirc) {
m_s.WinLircClient.Connect(m_s.strWinLircAddr);
}
m_s.UIceClient.SetHWND(m_pMainWnd->m_hWnd);
if(m_s.fUIce) {
m_s.UIceClient.Connect(m_s.strUIceAddr);
}
SendCommandLine(m_pMainWnd->m_hWnd);
RegisterHotkeys();
pFrame->SetFocus();
return TRUE;
}
UINT CMPlayerCApp::GetRemoteControlCodeMicrosoft(UINT nInputcode, HRAWINPUT hRawInput)
{
UINT dwSize = 0;
BYTE* pRawBuffer = NULL;
UINT nMceCmd = 0;
// Support for MCE remote control
GetRawInputData(hRawInput, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
if (dwSize > 0) {
pRawBuffer = DNew BYTE[dwSize];
if (GetRawInputData(hRawInput, RID_INPUT, pRawBuffer, &dwSize, sizeof(RAWINPUTHEADER)) != -1) {
RAWINPUT* raw = (RAWINPUT*) pRawBuffer;
if(raw->header.dwType == RIM_TYPEHID) {
nMceCmd = 0x10000 + (raw->data.hid.bRawData[1] | raw->data.hid.bRawData[2] << 8);
}
}
delete [] pRawBuffer;
}
return nMceCmd;
}
UINT CMPlayerCApp::GetRemoteControlCodeSRM7500(UINT nInputcode, HRAWINPUT hRawInput)
{
UINT dwSize = 0;
BYTE* pRawBuffer = NULL;
UINT nMceCmd = 0;
GetRawInputData(hRawInput, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
if (dwSize > 21) {
pRawBuffer = DNew BYTE[dwSize];
if (GetRawInputData(hRawInput, RID_INPUT, pRawBuffer, &dwSize, sizeof(RAWINPUTHEADER)) != -1) {
RAWINPUT* raw = (RAWINPUT*) pRawBuffer;
// data.hid.bRawData[21] set to one when key is pressed
if(raw->header.dwType == RIM_TYPEHID && raw->data.hid.bRawData[21] == 1) {
// data.hid.bRawData[21] has keycode
switch (raw->data.hid.bRawData[20]) {
case 0x0033 :
nMceCmd = MCE_DETAILS;
break;
case 0x0022 :
nMceCmd = MCE_GUIDE;
break;
case 0x0036 :
nMceCmd = MCE_MYTV;
break;
case 0x0026 :
nMceCmd = MCE_RECORDEDTV;
break;
case 0x0005 :
nMceCmd = MCE_RED;
break;
case 0x0002 :
nMceCmd = MCE_GREEN;
break;
case 0x0045 :
nMceCmd = MCE_YELLOW;
break;
case 0x0046 :
nMceCmd = MCE_BLUE;
break;
case 0x000A :
nMceCmd = MCE_MEDIA_PREVIOUSTRACK;
break;
case 0x004A :
nMceCmd = MCE_MEDIA_NEXTTRACK;
break;
}
}
}
delete [] pRawBuffer;
}
return nMceCmd;
}
void CMPlayerCApp::RegisterHotkeys()
{
RAWINPUTDEVICELIST InputDeviceList[50];
UINT nInputDeviceCount = countof(InputDeviceList);
RID_DEVICE_INFO DevInfo;
RAWINPUTDEVICE MCEInputDevice[] = {
// usUsagePage usUsage dwFlags hwndTarget
{ 0xFFBC, 0x88, 0, NULL},
{ 0x000C, 0x01, 0, NULL},
{ 0x000C, 0x80, 0, NULL}
};
// Register MCE Remote Control raw input
for (int i=0; im_hWnd;
}
nInputDeviceCount = GetRawInputDeviceList (InputDeviceList, &nInputDeviceCount, sizeof(RAWINPUTDEVICELIST));
for (int i=0; i0) {
if (DevInfo.hid.dwVendorId == 0x00000471 && // Philips HID vendor id
DevInfo.hid.dwProductId == 0x00000617) { // IEEE802.15.4 RF Dongle (SRM 7500)
MCEInputDevice[0].usUsagePage = DevInfo.hid.usUsagePage;
MCEInputDevice[0].usUsage = DevInfo.hid.usUsage;
GetRemoteControlCode = GetRemoteControlCodeSRM7500;
}
}
}
RegisterRawInputDevices (MCEInputDevice, countof(MCEInputDevice), sizeof(RAWINPUTDEVICE));
if (m_s.fGlobalMedia) {
POSITION pos = m_s.wmcmds.GetHeadPosition();
while(pos) {
wmcmd& wc = m_s.wmcmds.GetNext(pos);
if (wc.appcmd != 0) {
RegisterHotKey(m_pMainWnd->m_hWnd, wc.appcmd, 0, GetVKFromAppCommand (wc.appcmd));
}
}
}
}
void CMPlayerCApp::UnregisterHotkeys()
{
if (m_s.fGlobalMedia) {
POSITION pos = m_s.wmcmds.GetHeadPosition();
while(pos) {
wmcmd& wc = m_s.wmcmds.GetNext(pos);
if (wc.appcmd != 0) {
UnregisterHotKey(m_pMainWnd->m_hWnd, wc.appcmd);
}
}
}
}
UINT CMPlayerCApp::GetVKFromAppCommand(UINT nAppCommand)
{
switch (nAppCommand) {
case APPCOMMAND_BROWSER_BACKWARD :
return VK_BROWSER_BACK;
case APPCOMMAND_BROWSER_FORWARD :
return VK_BROWSER_FORWARD;
case APPCOMMAND_BROWSER_REFRESH :
return VK_BROWSER_REFRESH;
case APPCOMMAND_BROWSER_STOP :
return VK_BROWSER_STOP;
case APPCOMMAND_BROWSER_SEARCH :
return VK_BROWSER_SEARCH;
case APPCOMMAND_BROWSER_FAVORITES :
return VK_BROWSER_FAVORITES;
case APPCOMMAND_BROWSER_HOME :
return VK_BROWSER_HOME;
case APPCOMMAND_VOLUME_MUTE :
return VK_VOLUME_MUTE;
case APPCOMMAND_VOLUME_DOWN :
return VK_VOLUME_DOWN;
case APPCOMMAND_VOLUME_UP :
return VK_VOLUME_UP;
case APPCOMMAND_MEDIA_NEXTTRACK :
return VK_MEDIA_NEXT_TRACK;
case APPCOMMAND_MEDIA_PREVIOUSTRACK :
return VK_MEDIA_PREV_TRACK;
case APPCOMMAND_MEDIA_STOP :
return VK_MEDIA_STOP;
case APPCOMMAND_MEDIA_PLAY_PAUSE :
return VK_MEDIA_PLAY_PAUSE;
case APPCOMMAND_LAUNCH_MAIL :
return VK_LAUNCH_MAIL;
case APPCOMMAND_LAUNCH_MEDIA_SELECT :
return VK_LAUNCH_MEDIA_SELECT;
case APPCOMMAND_LAUNCH_APP1 :
return VK_LAUNCH_APP1;
case APPCOMMAND_LAUNCH_APP2 :
return VK_LAUNCH_APP2;
}
return 0;
}
int CMPlayerCApp::ExitInstance()
{
m_s.UpdateData(true);
OleUninitialize();
return CWinApp::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// CMPlayerCApp message handlers
// App command to run the dialog
void CMPlayerCApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
void CMPlayerCApp::OnFileExit()
{
OnAppExit();
}
// CRemoteCtrlClient
CRemoteCtrlClient::CRemoteCtrlClient()
: m_pWnd(NULL)
, m_nStatus(DISCONNECTED)
{
}
void CRemoteCtrlClient::SetHWND(HWND hWnd)
{
CAutoLock cAutoLock(&m_csLock);
m_pWnd = CWnd::FromHandle(hWnd);
}
void CRemoteCtrlClient::Connect(CString addr)
{
CAutoLock cAutoLock(&m_csLock);
if(m_nStatus == CONNECTING && m_addr == addr) {
TRACE(_T("CRemoteCtrlClient (Connect): already connecting to %s\n"), addr);
return;
}
if(m_nStatus == CONNECTED && m_addr == addr) {
TRACE(_T("CRemoteCtrlClient (Connect): already connected to %s\n"), addr);
return;
}
m_nStatus = CONNECTING;
TRACE(_T("CRemoteCtrlClient (Connect): connecting to %s\n"), addr);
Close();
Create();
CString ip = addr.Left(addr.Find(':')+1).TrimRight(':');
int port = _tcstol(addr.Mid(addr.Find(':')+1), NULL, 10);
__super::Connect(ip, port);
m_addr = addr;
}
void CRemoteCtrlClient::OnConnect(int nErrorCode)
{
CAutoLock cAutoLock(&m_csLock);
m_nStatus = (nErrorCode == 0 ? CONNECTED : DISCONNECTED);
TRACE(_T("CRemoteCtrlClient (OnConnect): %d\n"), nErrorCode);
}
void CRemoteCtrlClient::OnClose(int nErrorCode)
{
CAutoLock cAutoLock(&m_csLock);
if(m_hSocket != INVALID_SOCKET && m_nStatus == CONNECTED) {
TRACE(_T("CRemoteCtrlClient (OnClose): connection lost\n"));
}
m_nStatus = DISCONNECTED;
TRACE(_T("CRemoteCtrlClient (OnClose): %d\n"), nErrorCode);
}
void CRemoteCtrlClient::OnReceive(int nErrorCode)
{
if(nErrorCode != 0 || !m_pWnd) {
return;
}
CStringA str;
int ret = Receive(str.GetBuffer(256), 255, 0);
if(ret <= 0) {
return;
}
str.ReleaseBuffer(ret);
TRACE(_T("CRemoteCtrlClient (OnReceive): %s\n"), CString(str));
OnCommand(str);
__super::OnReceive(nErrorCode);
}
void CRemoteCtrlClient::ExecuteCommand(CStringA cmd, int repcnt)
{
cmd.Trim();
if(cmd.IsEmpty()) {
return;
}
cmd.Replace(' ', '_');
CAppSettings& s = AfxGetAppSettings();
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos) {
wmcmd wc = s.wmcmds.GetNext(pos);
CStringA name = TToA(wc.GetName());
name.Replace(' ', '_');
if((repcnt == 0 && wc.rmrepcnt == 0 || wc.rmrepcnt > 0 && (repcnt%wc.rmrepcnt) == 0)
&& (!name.CompareNoCase(cmd) || !wc.rmcmd.CompareNoCase(cmd) || wc.cmd == (WORD)strtol(cmd, NULL, 10))) {
CAutoLock cAutoLock(&m_csLock);
TRACE(_T("CRemoteCtrlClient (calling command): %s\n"), wc.GetName());
m_pWnd->SendMessage(WM_COMMAND, wc.cmd);
break;
}
}
}
// CWinLircClient
CWinLircClient::CWinLircClient()
{
}
void CWinLircClient::OnCommand(CStringA str)
{
TRACE(_T("CWinLircClient (OnCommand): %s\n"), CString(str));
int i = 0, j = 0, repcnt = 0;
for(CStringA token = str.Tokenize(" ", i);
!token.IsEmpty();
token = str.Tokenize(" ", i), j++) {
if(j == 1) {
repcnt = strtol(token, NULL, 16);
} else if(j == 2) {
ExecuteCommand(token, repcnt);
}
}
}
// CUIceClient
CUIceClient::CUIceClient()
{
}
void CUIceClient::OnCommand(CStringA str)
{
TRACE(_T("CUIceClient (OnCommand): %s\n"), CString(str));
CStringA cmd;
int i = 0, j = 0;
for(CStringA token = str.Tokenize("|", i);
!token.IsEmpty();
token = str.Tokenize("|", i), j++) {
if(j == 0) {
cmd = token;
} else if(j == 1) {
ExecuteCommand(cmd, strtol(token, NULL, 16));
}
}
}
void CMPlayerCApp::OnHelpShowcommandlineswitches()
{
ShowCmdlnSwitches();
}
//
void GetCurDispMode(dispmode& dm, CString& DisplayName)
{
HDC hDC;
CString DisplayName1 = DisplayName;
if ((DisplayName == _T("Current")) || (DisplayName == _T(""))) {
CMonitor monitor;
CMonitors monitors;
monitor = monitors.GetNearestMonitor(AfxGetApp()->m_pMainWnd);
monitor.GetName(DisplayName1);
}
hDC = CreateDC(DisplayName1, NULL, NULL, NULL);
if(hDC) {
dm.fValid = true;
dm.size = CSize(GetDeviceCaps(hDC, HORZRES), GetDeviceCaps(hDC, VERTRES));
dm.bpp = GetDeviceCaps(hDC, BITSPIXEL);
dm.freq = GetDeviceCaps(hDC, VREFRESH);
DeleteDC(hDC);
}
}
bool GetDispMode(int i, dispmode& dm, CString& DisplayName)
{
DEVMODE devmode;
CString DisplayName1 = DisplayName;
devmode.dmSize = sizeof(DEVMODE);
if ((DisplayName == _T("Current")) || (DisplayName == _T(""))) {
CMonitor monitor;
CMonitors monitors;
monitor = monitors.GetNearestMonitor(AfxGetApp()->m_pMainWnd);
monitor.GetName(DisplayName1);
}
if(!EnumDisplaySettings(DisplayName1, i, &devmode)) {
return(false);
}
dm.fValid = true;
dm.size = CSize(devmode.dmPelsWidth, devmode.dmPelsHeight);
dm.bpp = devmode.dmBitsPerPel;
dm.freq = devmode.dmDisplayFrequency;
dm.dmDisplayFlags = devmode.dmDisplayFlags;
return(true);
}
void SetDispMode(dispmode& dm, CString& DisplayName)
{
dispmode dm1;
GetCurDispMode(dm1, DisplayName);
if ((dm.size == dm1.size) && (dm.bpp == dm1.bpp) && (dm.freq == dm1.freq)) {
return;
}
if(!dm.fValid) {
return;
}
DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = dm.size.cx;
dmScreenSettings.dmPelsHeight = dm.size.cy;
dmScreenSettings.dmBitsPerPel = dm.bpp;
dmScreenSettings.dmDisplayFrequency = dm.freq;
dmScreenSettings.dmDisplayFlags = dm.dmDisplayFlags;
dmScreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
CString DisplayName1 = DisplayName;
if ((DisplayName == _T("Current")) || (DisplayName == _T(""))) {
CMonitor monitor;
CMonitors monitors;
monitor = monitors.GetNearestMonitor(AfxGetApp()->m_pMainWnd);
monitor.GetName(DisplayName1);
}
if(AfxGetAppSettings().fRestoreResAfterExit) {
ChangeDisplaySettingsEx(DisplayName1, &dmScreenSettings, NULL, CDS_FULLSCREEN, NULL);
} else {
ChangeDisplaySettingsEx(DisplayName1, &dmScreenSettings, NULL, NULL, NULL);
}
}
void SetAudioRenderer(int AudioDevNo)
{
CStringArray m_AudioRendererDisplayNames;
AfxGetMyApp()->m_AudioRendererDisplayName_CL = _T("");
m_AudioRendererDisplayNames.Add(_T(""));
int i=2;
BeginEnumSysDev(CLSID_AudioRendererCategory, pMoniker) {
LPOLESTR olestr = NULL;
if(FAILED(pMoniker->GetDisplayName(0, 0, &olestr))) {
continue;
}
CStringW str(olestr);
CoTaskMemFree(olestr);
m_AudioRendererDisplayNames.Add(CString(str));
i++;
}
EndEnumSysDev
m_AudioRendererDisplayNames.Add(AUDRNDT_NULL_COMP);
m_AudioRendererDisplayNames.Add(AUDRNDT_NULL_UNCOMP);
m_AudioRendererDisplayNames.Add(AUDRNDT_MPC);
i+=3;
if (AudioDevNo>=1 && AudioDevNo<=i) {
AfxGetMyApp()->m_AudioRendererDisplayName_CL = m_AudioRendererDisplayNames[AudioDevNo-1];
}
}
void SetHandCursor(HWND m_hWnd, UINT nID)
{
SetClassLongPtr(GetDlgItem(m_hWnd, nID), GCLP_HCURSOR, (long) AfxGetApp()->LoadStandardCursor(IDC_HAND));
}
#include
#include
#include // put this before the first detours macro above to see an ICE with vc71 :)
#include
typedef CAtlRegExp CAtlRegExpT;
typedef CAtlREMatchContext CAtlREMatchContextT;
bool FindRedir(CUrl& src, CString ct, CString& body, CAtlList& urls, CAutoPtrList& res)
{
POSITION pos = res.GetHeadPosition();
while(pos) {
CAtlRegExpT* re = res.GetNext(pos);
CAtlREMatchContextT mc;
const CAtlREMatchContextT::RECHAR* s = (LPCTSTR)body;
const CAtlREMatchContextT::RECHAR* e = NULL;
for(; s && re->Match(s, &mc, &e); s = e) {
const CAtlREMatchContextT::RECHAR* szStart = 0;
const CAtlREMatchContextT::RECHAR* szEnd = 0;
mc.GetMatch(0, &szStart, &szEnd);
CString url;
url.Format(_T("%.*s"), szEnd - szStart, szStart);
url.Trim();
if(url.CompareNoCase(_T("asf path")) == 0) {
continue;
}
CUrl dst;
dst.CrackUrl(CString(url));
if(_tcsicmp(src.GetSchemeName(), dst.GetSchemeName())
|| _tcsicmp(src.GetHostName(), dst.GetHostName())
|| _tcsicmp(src.GetUrlPath(), dst.GetUrlPath())) {
urls.AddTail(url);
} else {
// recursive
urls.RemoveAll();
break;
}
}
}
return urls.GetCount() > 0;
}
bool FindRedir(CString& fn, CString ct, CAtlList& fns, CAutoPtrList& res)
{
CString body;
CTextFile f(CTextFile::ANSI);
if(f.Open(fn)) for(CString tmp; f.ReadString(tmp); body += tmp + '\n') {
;
}
CString dir = fn.Left(max(fn.ReverseFind('/'), fn.ReverseFind('\\'))+1); // "ReverseFindOneOf"
POSITION pos = res.GetHeadPosition();
while(pos) {
CAtlRegExpT* re = res.GetNext(pos);
CAtlREMatchContextT mc;
const CAtlREMatchContextT::RECHAR* s = (LPCTSTR)body;
const CAtlREMatchContextT::RECHAR* e = NULL;
for(; s && re->Match(s, &mc, &e); s = e) {
const CAtlREMatchContextT::RECHAR* szStart = 0;
const CAtlREMatchContextT::RECHAR* szEnd = 0;
mc.GetMatch(0, &szStart, &szEnd);
CString fn2;
fn2.Format(_T("%.*s"), szEnd - szStart, szStart);
fn2.Trim();
if(!fn2.CompareNoCase(_T("asf path"))) {
continue;
}
if(fn2.Find(_T("EXTM3U")) == 0 || fn2.Find(_T("#EXTINF")) == 0) {
continue;
}
if(fn2.Find(_T(":")) < 0 && fn2.Find(_T("\\\\")) != 0 && fn2.Find(_T("//")) != 0) {
CPath p;
p.Combine(dir, fn2);
fn2 = (LPCTSTR)p;
}
if(!fn2.CompareNoCase(fn)) {
continue;
}
fns.AddTail(fn2);
}
}
return fns.GetCount() > 0;
}
CStringA GetContentType(CString fn, CAtlList* redir)
{
CUrl url;
CString ct, body;
if(fn.Find(_T("://")) >= 0) {
url.CrackUrl(fn);
if(_tcsicmp(url.GetSchemeName(), _T("pnm")) == 0) {
return "audio/x-pn-realaudio";
}
if(_tcsicmp(url.GetSchemeName(), _T("mms")) == 0) {
return "video/x-ms-asf";
}
if(_tcsicmp(url.GetSchemeName(), _T("http")) != 0) {
return "";
}
DWORD ProxyEnable = 0;
CString ProxyServer;
DWORD ProxyPort = 0;
ULONG len = 256+1;
CRegKey key;
if(ERROR_SUCCESS == key.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), KEY_READ)
&& ERROR_SUCCESS == key.QueryDWORDValue(_T("ProxyEnable"), ProxyEnable) && ProxyEnable
&& ERROR_SUCCESS == key.QueryStringValue(_T("ProxyServer"), ProxyServer.GetBufferSetLength(256), &len)) {
ProxyServer.ReleaseBufferSetLength(len);
CAtlList sl;
ProxyServer = Explode(ProxyServer, sl, ';');
if(sl.GetCount() > 1) {
POSITION pos = sl.GetHeadPosition();
while(pos) {
CAtlList sl2;
if(!Explode(sl.GetNext(pos), sl2, '=', 2).CompareNoCase(_T("http"))
&& sl2.GetCount() == 2) {
ProxyServer = sl2.GetTail();
break;
}
}
}
ProxyServer = Explode(ProxyServer, sl, ':');
if(sl.GetCount() > 1) {
ProxyPort = _tcstol(sl.GetTail(), NULL, 10);
}
}
CSocket s;
s.Create();
if(s.Connect(
ProxyEnable ? ProxyServer : url.GetHostName(),
ProxyEnable ? ProxyPort : url.GetPortNumber())) {
CStringA host = CStringA(url.GetHostName());
CStringA path = CStringA(url.GetUrlPath()) + CStringA(url.GetExtraInfo());
if(ProxyEnable) {
path = "http://" + host + path;
}
CStringA hdr;
hdr.Format(
"GET %s HTTP/1.0\r\n"
"User-Agent: Media Player Classic\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"\r\n", path, host);
// MessageBox(NULL, CString(hdr), _T("Sending..."), MB_OK);
if(s.Send((LPCSTR)hdr, hdr.GetLength()) < hdr.GetLength()) {
return "";
}
hdr.Empty();
while(1) {
CStringA str;
str.ReleaseBuffer(s.Receive(str.GetBuffer(256), 256)); // SOCKET_ERROR == -1, also suitable for ReleaseBuffer
if(str.IsEmpty()) {
break;
}
hdr += str;
int hdrend = hdr.Find("\r\n\r\n");
if(hdrend >= 0) {
body = hdr.Mid(hdrend+4);
hdr = hdr.Left(hdrend);
break;
}
}
// MessageBox(NULL, CString(hdr), _T("Received..."), MB_OK);
CAtlList sl;
Explode(hdr, sl, '\n');
POSITION pos = sl.GetHeadPosition();
while(pos) {
CStringA& hdrline = sl.GetNext(pos);
CAtlList sl2;
Explode(hdrline, sl2, ':', 2);
CStringA field = sl2.RemoveHead().MakeLower();
if(field == "location" && !sl2.IsEmpty()) {
return GetContentType(CString(sl2.GetHead()), redir);
}
if(field == "content-type" && !sl2.IsEmpty()) {
ct = sl2.GetHead();
}
}
while(body.GetLength() < 256) {
CStringA str;
str.ReleaseBuffer(s.Receive(str.GetBuffer(256), 256)); // SOCKET_ERROR == -1, also suitable for ReleaseBuffer
if(str.IsEmpty()) {
break;
}
body += str;
}
if(body.GetLength() >= 8) {
CStringA str = TToA(body);
if(!strncmp((LPCSTR)str, ".ra", 3)) {
return "audio/x-pn-realaudio";
}
if(!strncmp((LPCSTR)str, ".RMF", 4)) {
return "audio/x-pn-realaudio";
}
if(*(DWORD*)(LPCSTR)str == 0x75b22630) {
return "video/x-ms-wmv";
}
if(!strncmp((LPCSTR)str+4, "moov", 4)) {
return "video/quicktime";
}
}
if(redir && (ct == _T("audio/x-scpls") || ct == _T("audio/x-mpegurl"))) {
while(body.GetLength() < 4*1024) { // should be enough for a playlist...
CStringA str;
str.ReleaseBuffer(s.Receive(str.GetBuffer(256), 256)); // SOCKET_ERROR == -1, also suitable for ReleaseBuffer
if(str.IsEmpty()) {
break;
}
body += str;
}
}
}
} else if(!fn.IsEmpty()) {
CPath p(fn);
CString ext = p.GetExtension().MakeLower();
if(ext == _T(".asx")) {
ct = _T("video/x-ms-asf");
} else if(ext == _T(".pls")) {
ct = _T("audio/x-scpls");
} else if(ext == _T(".m3u")) {
ct = _T("audio/x-mpegurl");
} else if(ext == _T(".qtl")) {
ct = _T("application/x-quicktimeplayer");
} else if(ext == _T(".mpcpl")) {
ct = _T("application/x-mpc-playlist");
} else if(ext == _T(".bdmv")) {
ct = _T("application/x-bdmv-playlist");
}
if(FILE* f = _tfopen(fn, _T("rb"))) {
CStringA str;
str.ReleaseBufferSetLength(fread(str.GetBuffer(10240), 1, 10240, f));
body = AToT(str);
fclose(f);
}
}
if(body.GetLength() >= 4) { // here only those which cannot be opened through dshow
CStringA str = TToA(body);
if(!strncmp((LPCSTR)str, ".ra", 3)) {
return "audio/x-pn-realaudio";
}
if(!strncmp((LPCSTR)str, "FWS", 3)) {
return "application/x-shockwave-flash";
}
}
if(redir && !ct.IsEmpty()) {
CAutoPtrList res;
CAutoPtr re;
if(ct == _T("video/x-ms-asf")) {
// ...://..."/>
re.Attach(DNew CAtlRegExpT());
if(re && REPARSE_ERROR_OK == re->Parse(_T("{[a-zA-Z]+://[^\n\">]*}"), FALSE)) {
res.AddTail(re);
}
// Ref#n= ...://...\n
re.Attach(DNew CAtlRegExpT());
if(re && REPARSE_ERROR_OK == re->Parse(_T("Ref\\z\\b*=\\b*[\"]*{([a-zA-Z]+://[^\n\"]+}"), FALSE)) {
res.AddTail(re);
}
} else if(ct == _T("audio/x-scpls")) {
// File1=...\n
re.Attach(DNew CAtlRegExp<>());
if(re && REPARSE_ERROR_OK == re->Parse(_T("file\\z\\b*=\\b*[\"]*{[^\n\"]+}"), FALSE)) {
res.AddTail(re);
}
} else if(ct == _T("audio/x-mpegurl")) {
// #comment
// ...
re.Attach(DNew CAtlRegExp<>());
if(re && REPARSE_ERROR_OK == re->Parse(_T("{[^#][^\n]+}"), FALSE)) {
res.AddTail(re);
}
} else if(ct == _T("audio/x-pn-realaudio")) {
// rtsp://...
re.Attach(DNew CAtlRegExp<>());
if(re && REPARSE_ERROR_OK == re->Parse(_T("{rtsp://[^\n]+}"), FALSE)) {
res.AddTail(re);
}
}
if(!body.IsEmpty()) {
if(fn.Find(_T("://")) >= 0) {
FindRedir(url, ct, body, *redir, res);
} else {
FindRedir(fn, ct, *redir, res);
}
}
}
return TToA(ct);
}
COLORPROPERTY_RANGE* CMPlayerCApp::GetColorControl(ControlType nFlag)
{
switch (nFlag) {
case Brightness :
return &m_ColorControl[0];
case Contrast :
return &m_ColorControl[1];
case Hue :
return &m_ColorControl[2];
case Saturation :
return &m_ColorControl[3];
}
return NULL;
}
LPCTSTR CMPlayerCApp::GetSatelliteDll(int nLanguage)
{
switch (nLanguage) {
case 1: // French
return _T("mpcresources.fr.dll");
case 2: // German
return _T("mpcresources.de.dll");
case 3: // Russian
return _T("mpcresources.ru.dll");
case 4: // Turkish
return _T("mpcresources.tr.dll");
case 5: // Czech
return _T("mpcresources.cz.dll");
case 6: // Spanish
return _T("mpcresources.es.dll");
case 7: // Hungarian
return _T("mpcresources.hu.dll");
case 8: // Korean
return _T("mpcresources.kr.dll");
case 9: // Polish
return _T("mpcresources.pl.dll");
case 10: // Ukrainian
return _T("mpcresources.ua.dll");
case 11: // Italian
return _T("mpcresources.it.dll");
case 12 : // Slovak
return _T("mpcresources.sk.dll");
case 13 : // Chinese (Simplified)
return _T("mpcresources.sc.dll");
case 14 : // Chinese (Traditional)
return _T("mpcresources.tc.dll");
case 15 : // Belarusian
return _T("mpcresources.by.dll");
case 16 : // Swedish
return _T("mpcresources.sv.dll");
case 17 : // Portuguese (Brasil)
return _T("mpcresources.br.dll");
case 18 : // Dutch
return _T("mpcresources.nl.dll");
case 19 : // Catalan
return _T("mpcresources.ca.dll");
case 20 : // Japanese
return _T("mpcresources.ja.dll");
case 21 : // Armenian
return _T("mpcresources.hy.dll");
}
return NULL;
}
int CMPlayerCApp::GetDefLanguage()
{
switch (GetUserDefaultUILanguage()) {
case 1036: // French
return 1;
case 1031: // German
return 2;
case 1049: // Russian
return 3;
case 1055: // Turkish
return 4;
case 1029: // Czech
return 5;
case 1034: // Spanish
return 6;
case 1038: // Hungarian
return 7;
case 1042: // Korean
return 8;
case 1045: // Polish
return 9;
case 1058: // Ukrainian
return 10;
case 1040: // Italian
return 11;
case 1051 : // Slovak
return 12;
case 2052 : // Chinese (simplified)
return 13;
case 3076 : // Chinese (traditional)
return 14;
case 1059 : // Belarusian
return 15;
case 1053 : // Swedish
return 16;
case 1046 : // Portuguese (brasil)
return 17;
case 1043 : // Dutch
return 18;
case 1027 : // Catalan
return 19;
case 1041 : // Japanese
return 20;
case 1067 : // Armenian
return 21;
default:
return 0;
}
}
void CMPlayerCApp::SetLanguage (int nLanguage)
{
AppSettings& s = AfxGetAppSettings();
HMODULE hMod = NULL;
LPCTSTR strSatellite;
strSatellite = GetSatelliteDll( nLanguage );
if ( strSatellite ) {
CFileVersionInfo Version;
CString strSatVersion;
if ( Version.Create(strSatellite) ) {
strSatVersion = Version.GetFileVersionEx();
CString needVersion = L"";
needVersion += MAKE_STR(MPC_VERSION_MAJOR);
needVersion += L".";
needVersion += MAKE_STR(MPC_VERSION_MINOR);
needVersion += L".";
needVersion += MAKE_STR(MPC_VERSION_PATCH);
needVersion += L".0";
if ( strSatVersion == needVersion ) {
hMod = LoadLibrary( strSatellite );
s.iLanguage = nLanguage;
} else {
// This message should stay in English!
MessageBox(NULL, _T("Your language pack will not work with this version. Please download a compatible one from the MPC-HC homepage."),
_T("Media Player Classic - Home Cinema"), MB_OK);
}
}
}
if ( hMod == NULL ) {
hMod = AfxGetApp()->m_hInstance;
s.iLanguage = 0;
}
if (AfxGetResourceHandle() != AfxGetApp()->m_hInstance) {
FreeLibrary(AfxGetResourceHandle());
}
AfxSetResourceHandle( hMod );
}
bool CMPlayerCApp::IsVSFilterInstalled()
{
bool result = false;
CRegKey key;
if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\Instance\\{9852A670-F845-491B-9BE6-EBD841B8A613}"), KEY_READ)) {
result = true;
}
return result;
}
bool CMPlayerCApp::HasEVR()
{
bool result = false;
CRegKey key;
if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\Instance\\{FA10746C-9B63-4B6C-BC49-FC300EA5F256}"), KEY_READ)) {
result = true;
}
return result;
}
HRESULT CMPlayerCApp::GetElevationType(TOKEN_ELEVATION_TYPE* ptet )
{
ASSERT( IsVistaOrAbove() );
ASSERT( ptet );
HRESULT hResult = E_FAIL; // assume an error occurred
HANDLE hToken = NULL;
if ( !::OpenProcessToken(
::GetCurrentProcess(),
TOKEN_QUERY,
&hToken ) ) {
ASSERT( FALSE );
return hResult;
}
DWORD dwReturnLength = 0;
if ( !::GetTokenInformation(
hToken,
TokenElevationType,
ptet,
sizeof( *ptet ),
&dwReturnLength ) ) {
ASSERT( FALSE );
} else {
ASSERT( dwReturnLength == sizeof( *ptet ) );
hResult = S_OK;
}
::CloseHandle( hToken );
return hResult;
}
void CMPlayerCApp::RunAsAdministrator(LPCTSTR strCommand, LPCTSTR strArgs, bool bWaitProcess)
{
SHELLEXECUTEINFO execinfo;
memset(&execinfo, 0, sizeof(execinfo));
execinfo.lpFile = strCommand;
execinfo.cbSize = sizeof(execinfo);
execinfo.lpVerb = _T("runas");
execinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execinfo.nShow = SW_SHOWDEFAULT;
execinfo.lpParameters = strArgs;
ShellExecuteEx(&execinfo);
if (bWaitProcess) {
WaitForSingleObject(execinfo.hProcess, INFINITE);
}
}
void CAboutDlg::OnHomepage(NMHDR *pNMHDR, LRESULT *pResult)
{
ShellExecute(m_hWnd, _T("open"), _T("http://mpc-hc.sourceforge.net/"), NULL, NULL, SW_SHOWDEFAULT);
*pResult = 0;
}
CRenderersData* GetRenderersData()
{
return &AfxGetMyApp()->m_Renderers;
}
CRenderersSettings& GetRenderersSettings()
{
return AfxGetAppSettings().m_RenderersSettings;
}