1777 lines
41 KiB
C++
1777 lines
41 KiB
C++
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: retrocfg.cpp
|
|
* Content: Implement the RetroConfigProcess function, and supporting functions
|
|
* History:
|
|
* Date By Reason
|
|
* ============
|
|
* 10/13/99 pnewson created
|
|
* 10/27/99 pnewson Fix: Bug #113692 & #113943 - support for new dplay app flags
|
|
* 11/04/99 pnewson Bug #115279 - added HWND to check audio setup calls
|
|
* - call audio setup automatically when retrofit enabled
|
|
* 12/03/99 scottle Merged into joy.cpl, and handed to pnewson to bug fix.
|
|
* 01/25/2000 pnewson Removed "unlisted games" checkbox
|
|
* 02/15/2000 pnewson Assorted bug fixes:
|
|
* millen 131837
|
|
* millen 131794
|
|
* millen 131889
|
|
* 03/23/2000 rodtoll Changed include dsound.x --> dsprv.h
|
|
* 04/05/2000 pnewson Changed format of "More Information" dialog box.
|
|
* 04/10/2000 pnewson changes to make 64bit builds work.
|
|
* 06/21/2000 rodtoll Bug #36213 - DX8 options panel should only appear on Millenium
|
|
* Panel will not load on any other OS.
|
|
* rodtoll Bug #30776 - Game options control panel gives Unexpected error if no device is present
|
|
* 09/28/2000 rodtoll Bug #46003 - DPVOICE: Memory leak when joy.cpl closed without clicking voice tab
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
#include <initguid.h>
|
|
#include <mmsystem.h>
|
|
#include <dsound.h>
|
|
#include <dsprv.h> // need for GUID instances
|
|
#include "dvoice.h"
|
|
#include "resource.h"
|
|
#include "retrocfg.h"
|
|
#include "dndbg.h"
|
|
#include "creg.h"
|
|
#include "dvosal.h"
|
|
#include <commctrl.h>
|
|
#include <shellapi.h>
|
|
#include <windowsx.h>
|
|
#include "joyarray.h"
|
|
|
|
#include "..\\..\\..\\dplay\\dplobby\\dplobby\\dplobby.h"
|
|
|
|
|
|
INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR RetrofitInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR RetrofitSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR RetrofitApplyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR RetrofitResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR RetrofitDetailsHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
INT_PTR CALLBACK WizardCancelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK WizardLaunchProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK ConfirmHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK SoundInitFailureProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK WizardErrorProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK VoiceEnabledProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK DetailsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK PrevHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
INT_PTR CALLBACK ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR ListViewLButtonDownHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR ListViewLButtonDblClkHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR ListViewKeydownHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
void ClearAllCheckboxes(HWND hDlg, HWND hwndListView, LONG lNumItems);
|
|
void MySetCheckState(HWND hwnd, int iItem, BOOL bChecked);
|
|
BOOL MyGetCheckState(HWND hwnd, int iItem);
|
|
BOOL MyToggleCheckState(HWND hwnd, int iItem);
|
|
|
|
static void RetrofitOnAdvHelp (LPARAM);
|
|
static void RetrofitOnContextMenu (WPARAM wParam, LPARAM lParam);
|
|
|
|
// These defines have been repeated here instead of inclucing dplobpr.h
|
|
// because it causes build problems.
|
|
#define DPLAY_REGISTRY_APPS L"Software\\Microsoft\\DirectPlay\\Applications"
|
|
#define REGSTR_VAL_FLAGS L"dwFlags"
|
|
#define REGSTR_VAL_FILE L"File"
|
|
#define REGSTR_VAL_PATH L"Path"
|
|
|
|
#define MAX_ICONS 2048
|
|
|
|
|
|
// Gasp! globals!
|
|
HIMAGELIST g_himagelist = NULL;
|
|
int g_iCheckboxEmptyIndex;
|
|
int g_iCheckboxFullIndex;
|
|
HINSTANCE g_hResDLLInstance;
|
|
LPDIRECTPLAYVOICETEST g_IDirectPlayVoiceSetup = NULL;
|
|
#define COLUMN_HEADER_SIZE 32
|
|
TCHAR g_tstrColumnHeader1[COLUMN_HEADER_SIZE];
|
|
TCHAR g_tstrColumnHeader2[COLUMN_HEADER_SIZE];
|
|
WNDPROC g_ListViewProc;
|
|
#define MESSAGE_BOX_SCRATCH_SIZE 128
|
|
|
|
// From Main.cpp
|
|
extern HINSTANCE ghInstance;
|
|
|
|
// externals for context help
|
|
extern const DWORD gaHelpIDs[];
|
|
|
|
typedef HRESULT (* PFGETDEVICEID)(LPCGUID, LPGUID);
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPVoiceCheckForDefaultDevices"
|
|
// DPVoiceCheckForDefaultDevices
|
|
//
|
|
// This function returns DV_OK if this system has at least a single playback
|
|
// and recording device.
|
|
//
|
|
HRESULT DPVoiceCheckForDefaultDevices()
|
|
{
|
|
HRESULT hr = DV_OK;
|
|
HMODULE hModule = NULL;
|
|
PFGETDEVICEID pfGetDeviceID = NULL;
|
|
|
|
GUID guidTmp;
|
|
|
|
hModule = LoadLibraryA("dsound.dll");
|
|
|
|
if (!hModule)
|
|
{
|
|
hr = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "Error loading dsound.dll - 0x%x", hr);
|
|
goto CHECKDEVICE_ERROR;
|
|
}
|
|
|
|
// attempt to get a pointer to the GetDeviceId function
|
|
pfGetDeviceID = (PFGETDEVICEID)GetProcAddress(hModule, "GetDeviceID");
|
|
|
|
if( !pfGetDeviceID )
|
|
{
|
|
hr = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "Error getting default devices - 0x%x", hr );
|
|
hr = DVERR_GENERIC;
|
|
goto CHECKDEVICE_ERROR;
|
|
}
|
|
|
|
hr = (*pfGetDeviceID)( &DSDEVID_DefaultPlayback, &guidTmp );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPF( DVF_ERRORLEVEL, "Error getting default playback device hr=0x%x", hr );
|
|
goto CHECKDEVICE_ERROR;
|
|
}
|
|
|
|
hr = (*pfGetDeviceID)( &DSDEVID_DefaultCapture, &guidTmp );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPF( DVF_ERRORLEVEL, "Error getting default capture device hr=0x%x", hr );
|
|
goto CHECKDEVICE_ERROR;
|
|
}
|
|
|
|
CHECKDEVICE_ERROR:
|
|
|
|
if( hModule )
|
|
FreeLibrary( hModule );
|
|
|
|
DPF_EXIT();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPVoiceCheckOS"
|
|
// DPVoiceCheckOS
|
|
//
|
|
// This function returns DV_OK if this is a platform the retrofit runs on.
|
|
//
|
|
// This function will return DVERR_GENERIC if this is a platform the retrofit does not
|
|
// run on.
|
|
//
|
|
HRESULT DPVoiceCheckOS()
|
|
{
|
|
OSVERSIONINFO osVerInfo;
|
|
LONG lLastError;
|
|
|
|
osVerInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
|
|
|
|
if( GetVersionEx( &osVerInfo ) )
|
|
{
|
|
// Win2K
|
|
if( osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
// NOTE: If we enable Whistler support we have to ensure that this returns an error
|
|
// if we're booting in safe-mode!
|
|
/*
|
|
// Whistler -- Major Version = 5 & Build # > 2195
|
|
if( osVerInfo.dwMajorVersion == 5 && osVerInfo.dwBuildNumber > 2195 )
|
|
{
|
|
return DV_OK;
|
|
}*/
|
|
|
|
return DVERR_GENERIC;
|
|
}
|
|
// Win9X
|
|
else
|
|
{
|
|
// Millenium Major = 4, Minor = 90
|
|
if( (HIBYTE(HIWORD(osVerInfo.dwBuildNumber)) == 4) &&
|
|
(LOBYTE(HIWORD(osVerInfo.dwBuildNumber)) == 90) )
|
|
{
|
|
return DV_OK;
|
|
}
|
|
|
|
return DVERR_GENERIC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lLastError = GetLastError();
|
|
|
|
DPF( 0, "Error getting version info: 0x%x", lLastError );
|
|
return DVERR_GENERIC;
|
|
}
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVoiceCPLInit"
|
|
HRESULT DVoiceCPLInit(void)
|
|
{
|
|
DPF_ENTER();
|
|
HRESULT hr = S_OK;
|
|
|
|
GUID guidTmp;
|
|
|
|
g_hResDLLInstance = ghInstance;
|
|
|
|
// Check to ensure we're on Millenium or Whistler. If we aren't we want to hide this
|
|
// control panel.
|
|
//
|
|
hr = DPVoiceCheckOS();
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPF( DVF_ERRORLEVEL, "Error checking OS. Not a supported OS hr=0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
// Check to ensure there is at least a default playback and default capture device in the
|
|
// system. If there is not we want to hide the control panel.
|
|
//
|
|
hr = DPVoiceCheckForDefaultDevices();
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPF( DVF_ERRORLEVEL, "Error checking for play/cap device hr=0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
if (FAILED(CoInitialize(NULL)))
|
|
{
|
|
DPF_EXIT();
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = CoCreateInstance(CLSID_DirectPlayVoiceTest,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlayVoiceTest,
|
|
(LPVOID *) &g_IDirectPlayVoiceSetup);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPF( DVF_ERRORLEVEL, "Failed to create test interface hr=0x%x", hr );
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return hr;
|
|
} // End DVoiceCPLInit();
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitProc"
|
|
INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
INT_PTR fRet;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG :
|
|
fRet = RetrofitInitDialogHandler(hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case WM_NOTIFY :
|
|
{
|
|
LPNMHDR lpnm = (LPNMHDR) lParam;
|
|
|
|
switch (lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE :
|
|
fRet = RetrofitSetActiveHandler(hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case PSN_APPLY :
|
|
fRet = RetrofitApplyHandler(hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case PSN_RESET :
|
|
fRet = RetrofitResetHandler(hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED :
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_DETAILS:
|
|
fRet = RetrofitDetailsHandler(hDlg, message, wParam, lParam);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
fRet = RetrofitDestroyHandler(hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case WM_HELP:
|
|
RetrofitOnAdvHelp(lParam);
|
|
return(TRUE);
|
|
|
|
case WM_CONTEXTMENU:
|
|
RetrofitOnContextMenu(wParam, lParam);
|
|
return(TRUE);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitInitDialogHandler"
|
|
INT_PTR RetrofitInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
CRegistry cregApps;
|
|
CRegistry cregApp;
|
|
DWORD dwIndex;
|
|
DWORD dwListViewIndex;
|
|
WCHAR swzBuffer[MAX_REGISTRY_STRING_SIZE];
|
|
TCHAR tszBuffer[MAX_REGISTRY_STRING_SIZE];
|
|
WCHAR swzFilename[MAX_REGISTRY_STRING_SIZE];
|
|
WCHAR swzPath[MAX_REGISTRY_STRING_SIZE];
|
|
TCHAR tszFilename[MAX_REGISTRY_STRING_SIZE];
|
|
TCHAR tszPathAndFile[MAX_REGISTRY_STRING_SIZE * 2 + 1];
|
|
DWORD dwStrLen;
|
|
HKEY hkApps;
|
|
LONG lRet;
|
|
HRESULT hr;
|
|
LVITEM lvitem;
|
|
LVCOLUMN lvcolumn;
|
|
RECT rect;
|
|
HWND hwndListView;
|
|
HICON hiLarge;
|
|
HICON hiSmall;
|
|
int iIconXSize;
|
|
int iIconYSize;
|
|
int iIconIndex;
|
|
int iScrollWidth;
|
|
DWORD dwGlobalFlags;
|
|
HICON hiconDefault;
|
|
HDC hdc;
|
|
TEXTMETRIC tm;
|
|
int iChars;
|
|
|
|
// create the image list for the icons
|
|
iIconXSize = GetSystemMetrics(SM_CXSMICON);
|
|
if (iIconXSize == 0)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
iIconYSize = GetSystemMetrics(SM_CYSMICON);
|
|
if (iIconYSize == 0)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
g_himagelist = ImageList_Create(iIconXSize, iIconYSize, ILC_MASK, 0, MAX_ICONS);
|
|
if (g_himagelist == NULL)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "ImageList_Create failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
// Load the default icon for the image list
|
|
hiconDefault = LoadIcon(g_hResDLLInstance, MAKEINTRESOURCE(IDI_LIST_DEFAULT));
|
|
if (hiconDefault == NULL)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "LoadIcon failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
// get a handle to the list view control
|
|
hwndListView = GetDlgItem(hDlg, IDC_LIST_GAMES);
|
|
if (hwndListView == NULL)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
// subclass the list view
|
|
g_ListViewProc = (WNDPROC)SetWindowLongPtr(hwndListView, GWLP_WNDPROC, (INT_PTR)ListViewSubclassProc);
|
|
if (g_ListViewProc == NULL)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "SetWindowLong failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
// add the enable column to the list view control
|
|
hdc = GetDC(hDlg);
|
|
if (hdc == NULL)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "GetDC failed");
|
|
goto error_level_0;
|
|
}
|
|
if (GetTextMetrics(hdc, &tm) == 0)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "GetTextMetrics failed");
|
|
goto error_level_0;
|
|
}
|
|
|
|
ZeroMemory(&lvcolumn, sizeof(lvcolumn));
|
|
lvcolumn.mask = LVCF_ORDER|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
|
|
lvcolumn.iOrder = 1;
|
|
lvcolumn.iSubItem = 1;
|
|
ZeroMemory(g_tstrColumnHeader2, COLUMN_HEADER_SIZE*sizeof(TCHAR));
|
|
iChars = LoadString(g_hResDLLInstance,
|
|
IDS_ENABLED_COLUMN_HEADER,
|
|
g_tstrColumnHeader2,
|
|
COLUMN_HEADER_SIZE);
|
|
if (iChars == 0)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "LoadString failed");
|
|
goto error_level_0;
|
|
}
|
|
|
|
lvcolumn.pszText = g_tstrColumnHeader2;
|
|
lvcolumn.cx = tm.tmAveCharWidth * iChars;
|
|
|
|
if (ListView_InsertColumn(hwndListView, 1, &lvcolumn) == -1)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_InsertColumn failed");
|
|
goto error_level_0;
|
|
}
|
|
|
|
// add the game column to the list view control
|
|
ZeroMemory(&lvcolumn, sizeof(lvcolumn));
|
|
lvcolumn.mask = LVCF_ORDER|LVCF_WIDTH|LVCF_TEXT;
|
|
lvcolumn.iOrder = 0;
|
|
|
|
if (!GetClientRect(hwndListView, &rect))
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "GetClientRect failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
iScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
|
|
if (iScrollWidth == 0)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed");
|
|
goto error_level_0;
|
|
}
|
|
lvcolumn.cx = rect.right - rect.left - iScrollWidth - (iChars * tm.tmAveCharWidth);
|
|
|
|
ZeroMemory(g_tstrColumnHeader1, COLUMN_HEADER_SIZE*sizeof(TCHAR));
|
|
iChars = LoadString(g_hResDLLInstance,
|
|
IDS_GAMES_COLUMN_HEADER,
|
|
g_tstrColumnHeader1,
|
|
COLUMN_HEADER_SIZE);
|
|
if (iChars == 0)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "LoadString failed");
|
|
goto error_level_0;
|
|
}
|
|
lvcolumn.pszText = g_tstrColumnHeader1;
|
|
|
|
if (ListView_InsertColumn(hwndListView, 0, &lvcolumn) == -1)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_InsertColumn failed");
|
|
goto error_level_0;
|
|
}
|
|
|
|
// put checkboxes into the list view control
|
|
//ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_CHECKBOXES);
|
|
ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_SUBITEMIMAGES);
|
|
|
|
// add the small image list to the list view control
|
|
ListView_SetImageList(hwndListView, g_himagelist, LVSIL_SMALL);
|
|
|
|
// add icons to the image list for selected and cleared checkboxes
|
|
hiSmall = (HICON)LoadImage(
|
|
g_hResDLLInstance,
|
|
MAKEINTRESOURCE(IDI_CHECKBOX_EMPTY),
|
|
IMAGE_ICON,
|
|
iIconXSize,
|
|
iIconYSize,
|
|
LR_SHARED);
|
|
if (hiSmall == NULL)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to load empty checkbox icon resource");
|
|
goto error_level_0;
|
|
}
|
|
g_iCheckboxEmptyIndex = ImageList_AddIcon(g_himagelist, hiSmall);
|
|
if (g_iCheckboxEmptyIndex == -1)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to add empty checkbox icon to image list");
|
|
goto error_level_0;
|
|
}
|
|
hiSmall = (HICON)LoadImage(
|
|
g_hResDLLInstance,
|
|
MAKEINTRESOURCE(IDI_CHECKBOX_FULL),
|
|
IMAGE_ICON,
|
|
iIconXSize,
|
|
iIconYSize,
|
|
LR_SHARED);
|
|
if (hiSmall == NULL)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to load full checkbox icon resource");
|
|
goto error_level_0;
|
|
}
|
|
g_iCheckboxFullIndex = ImageList_AddIcon(g_himagelist, hiSmall);
|
|
if (g_iCheckboxFullIndex == -1)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to add full checkbox icon to image list");
|
|
goto error_level_0;
|
|
}
|
|
|
|
// open the applications area of the registry
|
|
if (!cregApps.Open(HKEY_LOCAL_MACHINE, DPLAY_REGISTRY_APPS, FALSE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to open DirectPlay applications registry key");
|
|
goto error_level_0;
|
|
}
|
|
hkApps = cregApps.GetHandle();
|
|
|
|
// default the global checkbox to off
|
|
/*
|
|
if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, FALSE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
|
|
// don't bail, continue
|
|
}
|
|
*/
|
|
|
|
// get the dwFlags value from the root of the applications area
|
|
if (cregApps.ReadDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
|
|
{
|
|
// set the checkbox if indicated
|
|
/*
|
|
if (dwGlobalFlags & DPLAPP_AUTOVOICE)
|
|
{
|
|
if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, TRUE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
|
|
// don't bail, continue
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to read flags DirectPlay applications registry key");
|
|
// don't bail, continue
|
|
}
|
|
|
|
// enum the apps and add them to the list box
|
|
dwIndex = 0;
|
|
dwListViewIndex = 0;
|
|
while(1)
|
|
{
|
|
dwStrLen = MAX_REGISTRY_STRING_SIZE;
|
|
if (!cregApps.EnumKeys(swzBuffer, &dwStrLen, dwIndex))
|
|
{
|
|
// that's all, we're done.
|
|
break;
|
|
}
|
|
|
|
if (!cregApp.Open(hkApps, swzBuffer, FALSE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to open application registry key");
|
|
continue;
|
|
}
|
|
|
|
// get the app flags so we know if we want
|
|
// to add this item to the list.
|
|
DWORD dwFlags;
|
|
if (!cregApp.ReadDWORD(REGSTR_VAL_FLAGS, dwFlags))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::ReadDWORD failed");
|
|
// forgive this error, since apps registered with
|
|
// older versions of DirectPlay will not have
|
|
// flags entries, set dwFlags to zero.
|
|
dwFlags = 0;
|
|
}
|
|
|
|
if (dwFlags & DPLAPP_NOENUM || dwFlags & DPLAPP_SELFVOICE)
|
|
{
|
|
// This app is either hidden, or implements it's own
|
|
// voice comms. We don't want to add it to the list,
|
|
// so continuue with the next iteration.
|
|
++dwIndex;
|
|
cregApp.Close();
|
|
continue;
|
|
}
|
|
|
|
// get the name of the key in a TCHAR
|
|
if (!OSAL_WideToTChar(tszBuffer, swzBuffer, MAX_REGISTRY_STRING_SIZE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "OSAL_WideToAnsi failed");
|
|
++dwIndex;
|
|
cregApp.Close();
|
|
continue;
|
|
}
|
|
|
|
// get the application's icon
|
|
dwStrLen = MAX_REGISTRY_STRING_SIZE;
|
|
if (!cregApp.ReadString(REGSTR_VAL_FILE, swzFilename, &dwStrLen))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::ReadString failed");
|
|
++dwIndex;
|
|
cregApp.Close();
|
|
continue;
|
|
}
|
|
|
|
hr = OSAL_WideToTChar(tszFilename, swzFilename, dwStrLen);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "OSAL_WidToAnsi failed, code: %i", hr);
|
|
++dwIndex;
|
|
cregApp.Close();
|
|
continue;
|
|
}
|
|
|
|
dwStrLen = MAX_REGISTRY_STRING_SIZE;
|
|
if (!cregApp.ReadString(REGSTR_VAL_PATH, swzPath, &dwStrLen))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::ReadString failed");
|
|
++dwIndex;
|
|
cregApp.Close();
|
|
continue;
|
|
}
|
|
|
|
if (!cregApp.Close())
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
|
|
++dwIndex;
|
|
continue;
|
|
}
|
|
|
|
hr = OSAL_WideToTChar(tszPathAndFile, swzPath, MAX_REGISTRY_STRING_SIZE);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "OSAL_AllocAndConvertToANSI failed, code: %i", hr);
|
|
++dwIndex;
|
|
continue;
|
|
}
|
|
|
|
if (tszPathAndFile[_tcslen(tszPathAndFile)-1] != '\\')
|
|
{
|
|
// since there isn't one there, tack on the trailing backslash
|
|
_tcscat(tszPathAndFile, _T("\\"));
|
|
}
|
|
_tcscat(tszPathAndFile, tszFilename);
|
|
ExtractIconEx(tszPathAndFile, 0, &hiLarge, &hiSmall, 1);
|
|
|
|
// don't need the large icon.
|
|
if (hiLarge != NULL)
|
|
{
|
|
DestroyIcon(hiLarge);
|
|
}
|
|
|
|
// add the small icon to the image list if it is valid
|
|
if (hiSmall != NULL)
|
|
{
|
|
iIconIndex = ImageList_AddIcon(g_himagelist, hiSmall);
|
|
}
|
|
else
|
|
{
|
|
iIconIndex = ImageList_AddIcon(g_himagelist, hiconDefault);
|
|
}
|
|
|
|
if (iIconIndex == -1)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "ImageList_AddIcon failed, code: %i", lRet);
|
|
++dwIndex;
|
|
continue;
|
|
}
|
|
|
|
lvitem.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE;
|
|
lvitem.iImage = iIconIndex;
|
|
|
|
if (hiSmall != NULL)
|
|
{
|
|
DestroyIcon(hiSmall);
|
|
}
|
|
|
|
lvitem.iItem = dwListViewIndex;
|
|
lvitem.iSubItem = 0;
|
|
lvitem.state = 0;
|
|
lvitem.stateMask = 0;
|
|
lvitem.pszText = tszBuffer;
|
|
lvitem.cchTextMax = 0;
|
|
lvitem.lParam = dwFlags;
|
|
lvitem.iIndent = 0;
|
|
if (ListView_InsertItem(hwndListView, &lvitem) == -1)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_InsertItem failed");
|
|
++dwIndex;
|
|
continue;
|
|
}
|
|
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iItem = dwListViewIndex;
|
|
lvitem.iSubItem = 1;
|
|
// check the flags to see if this item should be initially selected
|
|
if (dwFlags & DPLAPP_AUTOVOICE)
|
|
{
|
|
// select this item in the list
|
|
lvitem.iImage = g_iCheckboxFullIndex;
|
|
}
|
|
else
|
|
{
|
|
lvitem.iImage = g_iCheckboxEmptyIndex;
|
|
}
|
|
if (ListView_SetItem(hwndListView, &lvitem) == -1)
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_SetItem failed");
|
|
ListView_DeleteItem(hwndListView, dwListViewIndex);
|
|
++dwIndex;
|
|
continue;
|
|
}
|
|
|
|
++dwIndex;
|
|
++dwListViewIndex;
|
|
}
|
|
|
|
if (!cregApps.Close())
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to close DirectPlay applications registry key");
|
|
}
|
|
|
|
// If there is at least one item in the list, set the focus to the first item
|
|
// in the list so it will be marked when the user first comes to this tab.
|
|
if (dwListViewIndex > 0)
|
|
{
|
|
ListView_SetItemState(hwndListView, 0, LVIS_FOCUSED, LVIS_FOCUSED);
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return TRUE;
|
|
|
|
error_level_0:
|
|
DPF_EXIT();
|
|
return TRUE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitSetActiveHandler"
|
|
INT_PTR RetrofitSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitApplyHandler"
|
|
INT_PTR RetrofitApplyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
LONG lRet;
|
|
LONG lNumItems;
|
|
LONG lIndex;
|
|
TCHAR tszItemText[MAX_REGISTRY_STRING_SIZE];
|
|
WCHAR swzItemText[MAX_REGISTRY_STRING_SIZE];
|
|
CRegistry cregApps;
|
|
CRegistry cregApp;
|
|
HKEY hkApps;
|
|
HWND hwndListView;
|
|
LVITEM lvitem;
|
|
DWORD dwFlags;
|
|
HRESULT hr1;
|
|
HRESULT hr2;
|
|
BOOL fItemsSelected;
|
|
INT_PTR intptr;
|
|
BOOL fTestRun = FALSE;
|
|
|
|
|
|
// Get a handle to the list view
|
|
hwndListView = GetDlgItem(hDlg, IDC_LIST_GAMES);
|
|
if (hwndListView == NULL)
|
|
{
|
|
lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
|
|
goto error_level_0;
|
|
}
|
|
|
|
// Get the number of items in the list view
|
|
lNumItems = ListView_GetItemCount(hwndListView);
|
|
|
|
// Prescan the list to see if any items have been
|
|
// checked off.
|
|
fItemsSelected = FALSE;
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iSubItem = 1;
|
|
for (lIndex = 0; lIndex < lNumItems; ++lIndex)
|
|
{
|
|
lvitem.iItem = lIndex;
|
|
if (!ListView_GetItem(hwndListView, &lvitem))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
|
|
goto error_level_0;
|
|
}
|
|
|
|
if (lvitem.iImage == g_iCheckboxFullIndex)
|
|
{
|
|
fItemsSelected = TRUE;
|
|
}
|
|
}
|
|
|
|
// look at the checkbox for unlisted games as well
|
|
/*
|
|
if (IsDlgButtonChecked(hDlg, IDC_UNLISTEDCHECK) == BST_CHECKED)
|
|
{
|
|
fItemsSelected = TRUE;
|
|
}
|
|
*/
|
|
|
|
if (fItemsSelected)
|
|
{
|
|
// Before we allow the user to enable the retrofit, we are going
|
|
// to make sure that setup has been run on the default
|
|
// devices, and run it forcibly if required.
|
|
hr1 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, NULL, DVFLAGS_QUERYONLY);
|
|
switch (hr1)
|
|
{
|
|
case DV_FULLDUPLEX:
|
|
// The sound hardware is fine, do nothing special.
|
|
break;
|
|
|
|
case DV_HALFDUPLEX:
|
|
// The wizard has been run before, but the result was half duplex.
|
|
// Give the user the option to run the wizard again, or continue
|
|
// with the half duplex limitation.
|
|
intptr = DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_PREV_HALFDUPLEX),
|
|
hDlg, PrevHalfDuplexProc);
|
|
switch (intptr)
|
|
{
|
|
case IDOK:
|
|
// the user has accepted half duplex mode, exit the control panel
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
// the use hit the X or esc. Escape back to the control panel, and
|
|
// do not exit it
|
|
goto error_level_1;
|
|
|
|
case IDC_RUNTEST:
|
|
default:
|
|
// default should not occur, but treat as a run test
|
|
fTestRun = TRUE;
|
|
hr2 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, hDlg, 0);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// With any other result, either the wizard hasn't been run, or it failed
|
|
// really badly. Run it again, but warn the user we're about to run the wizard,
|
|
// and give them the chance to bail.
|
|
if (DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_LAUNCH),
|
|
hDlg, WizardLaunchProc) != IDOK)
|
|
{
|
|
// treat this as if they bailed out of the wizard itself.
|
|
fTestRun = TRUE;
|
|
hr2 = DVERR_USERCANCEL;
|
|
}
|
|
else
|
|
{
|
|
fTestRun = TRUE;
|
|
hr2 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, hDlg, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// if the test was run, deal with the results
|
|
if (fTestRun)
|
|
{
|
|
switch (hr2)
|
|
{
|
|
case DV_FULLDUPLEX:
|
|
// The user just exited from the wizard, so we don't want to
|
|
// kick them completely out of the control panel. They should
|
|
// have to hit OK again in the control panel.
|
|
goto error_level_1;
|
|
break;
|
|
|
|
case DV_HALFDUPLEX:
|
|
// the user is only getting half duplex, confirm that they want
|
|
// to use voice chat anyway. If they don't, clear all checkboxes
|
|
// and don't exit the control panel.
|
|
if (DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_CONFIRM_HALFDUPLEX),
|
|
hDlg, ConfirmHalfDuplexProc) != IDOK)
|
|
{
|
|
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
|
|
}
|
|
|
|
// The user just exited from the wizard, so we don't want to
|
|
// kick them completely out of the control panel. They should
|
|
// have to hit OK again in the control panel.
|
|
goto error_level_1;
|
|
|
|
case DVERR_SOUNDINITFAILURE:
|
|
// The sound test failed miserably. Let the user know they cannot use
|
|
// voice chat, clear all the checkboxes and exit the control panel
|
|
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
|
|
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_CONFIRM_SOUNDINITFAILURE),
|
|
hDlg, SoundInitFailureProc);
|
|
goto error_level_1;
|
|
|
|
case DVERR_USERCANCEL:
|
|
// The user canceled the wizard, inform them they cannot use
|
|
// voice chat and clear all the checkboxes. Don't exit the property sheet.
|
|
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
|
|
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_CANCELED),
|
|
hDlg, WizardCancelProc);
|
|
goto error_level_1;
|
|
|
|
default:
|
|
// Anything else is unexpect and should be treated as an error.
|
|
// Display an error message, clear the checkboxes, and DO exit the propery sheet
|
|
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
|
|
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_ERROR),
|
|
hDlg, WizardErrorProc);
|
|
goto error_level_1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we get here, the test was already run on the default
|
|
// devices, and it returned either halfduplex or fullduplex,
|
|
// so we can set the bits as we please.
|
|
|
|
// Open the applications registry key
|
|
if (!cregApps.Open(HKEY_LOCAL_MACHINE, DPLAY_REGISTRY_APPS, FALSE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::Open failed");
|
|
goto error_level_1;
|
|
}
|
|
hkApps = cregApps.GetHandle();
|
|
|
|
// set the autovoice bit - maintaint the state of the rest of the bits
|
|
// in case we add more global flags later
|
|
/*
|
|
if (!cregApps.ReadDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Error reading default flags from applications key");
|
|
dwGlobalFlags = 0;
|
|
// continue anyway
|
|
}
|
|
if (IsDlgButtonChecked(hDlg, IDC_UNLISTEDCHECK) == BST_CHECKED)
|
|
{
|
|
dwGlobalFlags |= DPLAPP_AUTOVOICE;
|
|
}
|
|
else
|
|
{
|
|
dwGlobalFlags &= ~DPLAPP_AUTOVOICE;
|
|
}
|
|
if (cregApps.WriteDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Error writing default flags to application key");
|
|
// continue anyway
|
|
}
|
|
*/
|
|
|
|
// loop through the items and set the app's flags according to
|
|
// the selected state of the list view
|
|
for (lIndex = 0; lIndex < lNumItems; ++lIndex)
|
|
{
|
|
// get the item info
|
|
lvitem.mask = LVIF_TEXT|LVIF_PARAM;
|
|
lvitem.iItem = lIndex;
|
|
lvitem.iSubItem = 0;
|
|
lvitem.state = 0;
|
|
lvitem.stateMask = 0;
|
|
lvitem.pszText = tszItemText;
|
|
lvitem.cchTextMax = MAX_REGISTRY_STRING_SIZE;
|
|
lvitem.iImage = 0;
|
|
lvitem.lParam = 0;
|
|
lvitem.iIndent = 0;
|
|
if (!ListView_GetItem(hwndListView, &lvitem))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
|
|
goto error_level_1;
|
|
}
|
|
|
|
dwFlags = (DWORD)lvitem.lParam;
|
|
|
|
if (!OSAL_TCharToWide(swzItemText, tszItemText, MAX_REGISTRY_STRING_SIZE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "OSAL_AnsiToWide failed");
|
|
goto error_level_1;
|
|
}
|
|
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iItem = lIndex;
|
|
lvitem.iSubItem = 1;
|
|
if (!ListView_GetItem(hwndListView, &lvitem))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
|
|
goto error_level_1;
|
|
}
|
|
|
|
if (lvitem.iImage == g_iCheckboxFullIndex)
|
|
{
|
|
dwFlags |= DPLAPP_AUTOVOICE;
|
|
}
|
|
else
|
|
{
|
|
dwFlags &= ~DPLAPP_AUTOVOICE;
|
|
}
|
|
|
|
if (!cregApp.Open(hkApps, swzItemText, FALSE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::Open failed");
|
|
goto error_level_1;
|
|
}
|
|
|
|
if (!cregApp.WriteDWORD(REGSTR_VAL_FLAGS, dwFlags))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::WriteDWORD failed");
|
|
goto error_level_1;
|
|
}
|
|
|
|
if (!cregApp.Close())
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
|
|
goto error_level_1;
|
|
}
|
|
}
|
|
|
|
if (!cregApps.Close())
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
|
|
goto error_level_1;
|
|
}
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
DPF_EXIT();
|
|
return TRUE;
|
|
|
|
error_level_1:
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
|
|
|
error_level_0:
|
|
DPF_EXIT();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitResetHandler"
|
|
INT_PTR RetrofitResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitDetailsHandler"
|
|
INT_PTR RetrofitDetailsHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_MOREINFO),
|
|
hDlg, DetailsProc);
|
|
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "RetrofitDestroyHandler"
|
|
INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
if( g_himagelist )
|
|
{
|
|
// clean up the image list
|
|
ImageList_Destroy(g_himagelist);
|
|
g_himagelist = NULL;
|
|
}
|
|
|
|
if( g_IDirectPlayVoiceSetup )
|
|
{
|
|
// release the IDirectPlayVoiceSetup interface
|
|
g_IDirectPlayVoiceSetup->Release();
|
|
g_IDirectPlayVoiceSetup = NULL;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "WizardCancelProc"
|
|
INT_PTR CALLBACK WizardCancelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_WARNING);
|
|
SendDlgItemMessage(hDlg, IDC_ICON_NOTCOMPLETE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "WizardLaunchProc"
|
|
INT_PTR CALLBACK WizardLaunchProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_INFORMATION);
|
|
SendDlgItemMessage(hDlg, IDC_ICON_INFORMATION, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "PrevHalfDuplexProc"
|
|
INT_PTR CALLBACK PrevHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_WARNING);
|
|
SendDlgItemMessage(hDlg, IDC_WARNING_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
case IDC_RUNTEST:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ConfirmHalfDuplexProc"
|
|
INT_PTR CALLBACK ConfirmHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_WARNING);
|
|
SendDlgItemMessage(hDlg, IDC_ICON_WARNING, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "SoundInitFailureProc"
|
|
INT_PTR CALLBACK SoundInitFailureProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_ERROR);
|
|
SendDlgItemMessage(hDlg, IDC_ICON_ERROR, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "WizardErrorProc"
|
|
INT_PTR CALLBACK WizardErrorProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_ERROR);
|
|
SendDlgItemMessage(hDlg, IDC_ICON_ERROR, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "VoiceEnabledProc"
|
|
INT_PTR CALLBACK VoiceEnabledProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
HICON hIcon;
|
|
|
|
fRet = FALSE;
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hIcon = LoadIcon(NULL, IDI_INFORMATION);
|
|
SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DetailsProc"
|
|
INT_PTR CALLBACK DetailsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
static TCHAR *szMoreInfo = NULL;
|
|
static const int c_iMoreInfoStrLen = 2048;
|
|
|
|
|
|
fRet = FALSE;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
/*
|
|
hIcon = LoadIcon(NULL, IDI_INFORMATION);
|
|
SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
hIcon = LoadIcon(NULL, IDI_WARNING);
|
|
SendDlgItemMessage(hDlg, IDC_WARNING_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
|
|
*/
|
|
szMoreInfo = (TCHAR*)malloc((c_iMoreInfoStrLen-1)*sizeof(TCHAR));
|
|
if (szMoreInfo != NULL)
|
|
{
|
|
if (LoadString(g_hResDLLInstance, IDS_VOICEMOREINFO, szMoreInfo, c_iMoreInfoStrLen) != 0)
|
|
{
|
|
SetDlgItemText(hDlg, IDC_MOREINFO, szMoreInfo);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return fRet;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ClearAllCheckboxes"
|
|
void ClearAllCheckboxes(HWND hDlg, HWND hwndListView, LONG lNumItems)
|
|
{
|
|
LONG lIndex;
|
|
|
|
// get a handle to the list view control
|
|
HWND hwnd = GetDlgItem(hDlg, IDC_LIST_GAMES);
|
|
if (hwnd == NULL)
|
|
{
|
|
LONG lRet = GetLastError();
|
|
DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
|
|
return;
|
|
}
|
|
|
|
for (lIndex = 0; lIndex < lNumItems; ++lIndex)
|
|
{
|
|
MySetCheckState(hwnd, lIndex, FALSE);
|
|
}
|
|
|
|
/*
|
|
if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, FALSE))
|
|
{
|
|
DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
|
|
}
|
|
*/
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
|
|
return;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ListViewSubclassProc"
|
|
INT_PTR CALLBACK ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
LRESULT lResult;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
ListViewLButtonDownHandler(hwnd, message, wParam, lParam);
|
|
break;
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
ListViewLButtonDblClkHandler(hwnd, message, wParam, lParam);
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
ListViewKeydownHandler(hwnd, message, wParam, lParam);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
lResult = CallWindowProc(g_ListViewProc, hwnd, message, wParam, lParam);
|
|
|
|
DPF_EXIT();
|
|
return lResult;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ListViewLButtonDownHandler"
|
|
INT_PTR ListViewLButtonDownHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
LVHITTESTINFO lvHitTestInfo;
|
|
lvHitTestInfo.pt.x = GET_X_LPARAM(lParam);
|
|
lvHitTestInfo.pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
ListView_SubItemHitTest(hwnd, &lvHitTestInfo);
|
|
|
|
if (lvHitTestInfo.flags & LVHT_ONITEMICON && lvHitTestInfo.iSubItem == 1)
|
|
{
|
|
MyToggleCheckState(hwnd, lvHitTestInfo.iItem);
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ListViewLButtonDblClkHandler"
|
|
INT_PTR ListViewLButtonDblClkHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
LVHITTESTINFO lvHitTestInfo;
|
|
lvHitTestInfo.pt.x = GET_X_LPARAM(lParam);
|
|
lvHitTestInfo.pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
ListView_HitTest(hwnd, &lvHitTestInfo);
|
|
|
|
if (lvHitTestInfo.flags & LVHT_ONITEMICON|LVHT_ONITEMLABEL)
|
|
{
|
|
LVITEM lvitem;
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iItem = lvHitTestInfo.iItem;
|
|
lvitem.iSubItem = 1;
|
|
|
|
if (ListView_GetItem(hwnd, &lvitem))
|
|
{
|
|
// we got the image, toggle the state
|
|
if (lvitem.iImage == g_iCheckboxEmptyIndex)
|
|
{
|
|
lvitem.iImage = g_iCheckboxFullIndex;
|
|
}
|
|
else
|
|
{
|
|
lvitem.iImage = g_iCheckboxEmptyIndex;
|
|
}
|
|
|
|
ListView_SetItem(hwnd, &lvitem);
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ListViewKeydownHandler"
|
|
INT_PTR ListViewKeydownHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
int iItem;
|
|
switch (wParam)
|
|
{
|
|
case VK_SPACE:
|
|
// The space bar was hit. Figure out if one of the
|
|
// list view items has focus and if so, toggle the
|
|
// checkbox state
|
|
iItem = ListView_GetNextItem(hwnd, -1, LVNI_FOCUSED|LVNI_SELECTED);
|
|
if (iItem != -1)
|
|
{
|
|
MyToggleCheckState(hwnd, iItem);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "MySetCheckState"
|
|
void MySetCheckState(HWND hwnd, int iItem, BOOL bChecked)
|
|
{
|
|
LVITEM lvitem;
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iItem = iItem;
|
|
lvitem.iSubItem = 1;
|
|
|
|
if (ListView_GetItem(hwnd, &lvitem))
|
|
{
|
|
// we got the image, set the check state
|
|
if (bChecked)
|
|
{
|
|
lvitem.iImage = g_iCheckboxFullIndex;
|
|
}
|
|
else
|
|
{
|
|
lvitem.iImage = g_iCheckboxEmptyIndex;
|
|
}
|
|
|
|
ListView_SetItem(hwnd, &lvitem);
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "MyGetCheckState"
|
|
BOOL MyGetCheckState(HWND hwnd, int iItem)
|
|
{
|
|
LVITEM lvitem;
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iItem = iItem;
|
|
lvitem.iSubItem = 1;
|
|
|
|
if (ListView_GetItem(hwnd, &lvitem))
|
|
{
|
|
// we got the image, return the state
|
|
if (lvitem.iImage == g_iCheckboxEmptyIndex)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "MyToggleCheckState"
|
|
BOOL MyToggleCheckState(HWND hwnd, int iItem)
|
|
{
|
|
LVITEM lvitem;
|
|
lvitem.mask = LVIF_IMAGE;
|
|
lvitem.iItem = iItem;
|
|
lvitem.iSubItem = 1;
|
|
BOOL fRet = FALSE;
|
|
|
|
if (ListView_GetItem(hwnd, &lvitem))
|
|
{
|
|
// we got the image, toggle the state
|
|
if (lvitem.iImage == g_iCheckboxEmptyIndex)
|
|
{
|
|
lvitem.iImage = g_iCheckboxFullIndex;
|
|
fRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
lvitem.iImage = g_iCheckboxEmptyIndex;
|
|
fRet = TRUE;
|
|
}
|
|
|
|
ListView_SetItem(hwnd, &lvitem);
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// copied verbatim from appman.cpp
|
|
////////////////////////////////////
|
|
#define STR_LEN_32 32 // used by these functions...
|
|
static void RetrofitOnAdvHelp(LPARAM lParam)
|
|
{
|
|
DNASSERT (lParam);
|
|
|
|
// point to help file
|
|
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
|
|
DNASSERT (pszHelpFileName);
|
|
|
|
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
|
|
{
|
|
if( ((LPHELPINFO)lParam)->iContextType == HELPINFO_WINDOW )
|
|
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, pszHelpFileName, HELP_WM_HELP, (ULONG_PTR)gaHelpIDs);
|
|
}
|
|
#ifdef _DEBUG
|
|
else OutputDebugString(TEXT("JOY.CPL: AppMan.cpp: OnAdvHelp: LoadString Failed to find IDS_HELPFILENAME!\n"));
|
|
#endif // _DEBUG
|
|
|
|
if( pszHelpFileName )
|
|
delete[] (pszHelpFileName);
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// copied verbatim from appman.cpp
|
|
////////////////////////////////////
|
|
static void RetrofitOnContextMenu(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// HWND hListCtrl = NULL
|
|
DNASSERT (wParam);
|
|
|
|
#if 0
|
|
hListCtrl = GetDlgItem((HWND) wParam, IDC_APPMAN_DRIVE_LIST);
|
|
|
|
// If you are on the ListCtrl...
|
|
if( (HWND)wParam == hListCtrl )
|
|
{
|
|
SetFocus(hListCtrl);
|
|
|
|
// Don't attempt if nothing selected
|
|
if( iItem != NO_ITEM )
|
|
OnListviewContextMenu(hListCtrl,lParam);
|
|
} else
|
|
#endif
|
|
{
|
|
// point to help file
|
|
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
|
|
DNASSERT (pszHelpFileName);
|
|
|
|
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
|
|
WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (ULONG_PTR)gaHelpIDs);
|
|
#ifdef _DEBUG
|
|
else OutputDebugString(TEXT("JOY.CPL: appman.cpp: OnContextMenu: LoadString Failed to find IDS_HELPFILENAME!\n"));
|
|
#endif // _DEBUG
|
|
|
|
if( pszHelpFileName )
|
|
delete[] (pszHelpFileName);
|
|
}
|
|
}
|
|
|