|
|
/*==========================================================================;
* * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: supervis.cpp * Content: Implements a process that oversees the full duplex * testing proceedure, watching for nasty conditions in * the two child processes that are used to implement the * actual tests. This is required because on some older * VXD drivers, attempting full duplex can hang the process * or even (grumble) lock the whole system. * History: * Date By Reason * ============ * 08/19/99 pnewson created * 10/27/99 pnewson change guid members from pointers to structs * 10/28/99 pnewson Bug #114176 updated DVSOUNDDEVICECONFIG struct * 11/04/99 pnewson Bug #115279 - fixed cancel processing * - fixed crash detection * - fixed multiple instance detection * - added HWND to check audio setup * - automatically advance after full duplex test * 11/30/99 pnewson parameter validation and default device mapping * 12/16/99 rodtoll Bug #119584 - Error code cleanup (Renamed runsetup error) * 01/21/2000 pnewson Update for UI revisions * 01/23/2000 pnewson Improvded feedback for fatal errors (millen bug 114508) * 01/24/2000 pnewson Prefix detected bug fix * 01/25/2000 pnewson Added support for DVFLAGS_WAVEIDS * 01/27/2000 rodtoll Updated with API changes * 02/08/2000 rodtoll Bug #131496 - Selecting DVTHRESHOLD_DEFAULT results in voice * never being detected * 03/03/2000 rodtoll Updated to handle alternative gamevoice build. * 03/23/2000 rodtoll Win64 updates * 04/04/2000 pnewson Added support for DVFLAGS_ALLOWBACK * Removed "Already Running" dialog box * 04/19/2000 rodtoll Bug #31106 - Grey out recording sliders when no vol control avail * 04/19/2000 pnewson Error handling cleanup * Clicking Volume button brings volume window to foreground * 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k on non-admin account * Bug #32952 Does not run on Windows 95 w/o IE4 installed * 05/03/2000 pnewson Bug #33878 - Wizard locks up when clicking Next/Cancel during speaker test * 05/17/2000 rodtoll Bug #34045 - Parameter validation error while running TestNet. * rodtoll Bug #34764 - Verifies capture device before render device * 06/28/2000 rodtoll Prefix Bug #38022 * 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard * 07/31/2000 rodtoll Bug #39590 - SB16 class soundcards are passing when they should fail * Half duplex code was being ignored in mic test portion. * 08/06/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles. * 08/28/2000 masonb Voice Merge: Changed ccomutil.h to ccomutil.h * 08/31/2000 rodtoll Bug #43804 - DVOICE: dwSensitivity structure member is confusing - should be dwThreshold * 11/29/2000 rodtoll Bug #48348 - DPVOICE: Modify wizard to make use of DirectPlay8 as the transport. * 02/04/2001 simonpow Bug #354859 - Fixes for PREfast spotted problems (Unitialised variables) ***************************************************************************/
#include "dxvtlibpch.h"
#ifndef WIN95
#define PROPSHEETPAGE_STRUCT_SIZE sizeof( PROPSHEETPAGE )
#define PROPSHEETHEAD_STRUCT_SIZE sizeof( PROPSHEETHEADER )
#else
#define PROPSHEETPAGE_STRUCT_SIZE PROPSHEETPAGE_V1_SIZE
#define PROPSHEETHEAD_STRUCT_SIZE PROPSHEETHEADER_V1_SIZE
#endif
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
// logical defines for registry values
#define REGVAL_NOTRUN 0
#define REGVAL_CRASHED 1
#define REGVAL_FAILED 2
#define REGVAL_PASSED 3
// local typedefs
typedef HRESULT (WINAPI *TDirectSoundEnumFnc)(LPDSENUMCALLBACK, LPVOID);
// local static functions
static HRESULT SupervisorQueryAudioSetup(CSupervisorInfo* psinfo); static HRESULT RunFullDuplexTest(CSupervisorInfo* lpsinfo); static HRESULT DoTests(CSupervisorInfo* lpsinfo); static HRESULT IssueCommands(CSupervisorInfo* lpsinfo); static HRESULT IssueShutdownCommand(CSupervisorIPC* lpipcSupervisor);
// callback functions
INT_PTR CALLBACK WelcomeProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK AlreadyRunningProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK PreviousCrashProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK FullDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK MicTestProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK MicTestFailedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK SpeakerTestProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK CompleteProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK FullDuplexFailedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK HalfDuplexFailedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
// Thread functions
DWORD WINAPI FullDuplexTestThreadProc(LPVOID lpvParam); DWORD WINAPI LoopbackTestThreadProc(LPVOID lpvParam);
// Message handlers
BOOL WelcomeInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL WelcomeSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL WelcomeBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL WelcomeNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL WelcomeResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexCompleteHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestLoopbackRunningHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestRecordStartHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestRecordStopHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestVScrollHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestRecAdvancedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestFailedInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestFailedSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestFailedRecordStopHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestFailedBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestFailedResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL MicTestFailedFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestVScrollHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestRecAdvancedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL SpeakerTestOutAdvancedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL CompleteInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL CompleteSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL CompleteLoopbackEndedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL CompleteFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL CompleteResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexFailedInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexFailedSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexFailedFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexFailedResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL FullDuplexFailedBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL HalfDuplexFailedInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL HalfDuplexFailedSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL HalfDuplexFailedFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL HalfDuplexFailedResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo); BOOL HalfDuplexFailedBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo);
// globals
HINSTANCE g_hResDLLInstance;
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CSupervisorInfo"
CSupervisorInfo::CSupervisorInfo() : m_hfTitle(NULL) , m_guidCaptureDevice(GUID_NULL) , m_guidRenderDevice(GUID_NULL) , m_hFullDuplexThread(NULL) , m_hLoopbackThreadExitEvent(NULL) , m_fAbortFullDuplex(FALSE) , m_hLoopbackThread(NULL) , m_hLoopbackShutdownEvent(NULL) , m_fVoiceDetected(FALSE) , m_hwndWizard(NULL) , m_hwndDialog(NULL) , m_hwndProgress(NULL) , m_hwndInputPeak(NULL) , m_hwndOutputPeak(NULL) , m_hwndInputVolumeSlider(NULL) , m_hwndOutputVolumeSlider(NULL) , m_lpdpvc(NULL) , m_hMutex(NULL) , m_uiWaveInDeviceId(0) , m_uiWaveOutDeviceId(0) , m_dwDeviceFlags(0) , m_fLoopbackRunning(FALSE) , m_fCritSecInited(FALSE) { DPF_ENTER();
ZeroMemory(&m_piSndVol32Record, sizeof(PROCESS_INFORMATION)); ZeroMemory(&m_piSndVol32Playback, sizeof(PROCESS_INFORMATION)); ZeroMemory(&m_woCaps, sizeof(WAVEOUTCAPS)); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::~CSupervisorInfo"
CSupervisorInfo::~CSupervisorInfo() { if (m_fCritSecInited) { DNDeleteCriticalSection(&m_csLock); } }
// this structure is only used by the next two functions, hence
// it is declared here for convenince.
struct SMoveWindowEnumProcParam { PROCESS_INFORMATION* lppi; int x; int y; BOOL fMoved; };
struct SBringToForegroundEnumProcParam { PROCESS_INFORMATION* lppi; BOOL fFound; };
#undef DPF_MODNAME
#define DPF_MODNAME "BringToForegroundWindowProc"
BOOL CALLBACK BringToForegroundWindowProc(HWND hwnd, LPARAM lParam) { SBringToForegroundEnumProcParam* param; param = (SBringToForegroundEnumProcParam*)lParam; DPFX(DPFPREP, DVF_INFOLEVEL, "looking for main window for pid: %i", param->lppi->dwProcessId);
DWORD dwProcessId; GetWindowThreadProcessId(hwnd, &dwProcessId); DPFX(DPFPREP, DVF_INFOLEVEL, "window: 0x%p has pid: 0x%08x", hwnd, dwProcessId); if (dwProcessId == param->lppi->dwProcessId) { TCHAR rgtchClassName[64]; GetClassName(hwnd, rgtchClassName, 64); if (_tcsnicmp(rgtchClassName, _T("Volume Control"), 64) == 0) { if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetWindowPos failed, code: 0x%x", GetLastError()); } else { param->fFound = TRUE; } } return FALSE; } return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "BringToForegroundWindowEnumProc"
BOOL CALLBACK BringToForegroundWindowEnumProc(HWND hwnd, LPARAM lParam) { SMoveWindowEnumProcParam* param; param = (SMoveWindowEnumProcParam*)lParam; DPFX(DPFPREP, DVF_INFOLEVEL, "looking for main window for pid: 0x%x", param->lppi->dwProcessId);
DWORD dwProcessId; GetWindowThreadProcessId(hwnd, &dwProcessId); DPFX(DPFPREP, DVF_INFOLEVEL, "window: 0x%p has pid: 0x%08x", hwnd, dwProcessId); if (dwProcessId == param->lppi->dwProcessId) { TCHAR rgtchClassName[64]; GetClassName(hwnd, rgtchClassName, 64); if (_tcsnicmp(rgtchClassName, _T("Volume Control"), 64) == 0) { if (!SetForegroundWindow(hwnd)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetForegroundWindow failed, code: 0x%x", GetLastError()); } } return FALSE; } return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MoveWindowEnumProc"
BOOL CALLBACK MoveWindowEnumProc(HWND hwnd, LPARAM lParam) { SMoveWindowEnumProcParam* param; param = (SMoveWindowEnumProcParam*)lParam; DPFX(DPFPREP, DVF_INFOLEVEL, "looking for main window for pid: %i", param->lppi->dwProcessId);
DWORD dwProcessId; GetWindowThreadProcessId(hwnd, &dwProcessId); DPFX(DPFPREP, DVF_INFOLEVEL, "window: 0x%p has pid: 0x%08x", hwnd, dwProcessId); if (dwProcessId == param->lppi->dwProcessId) { TCHAR rgtchClassName[64]; GetClassName(hwnd, rgtchClassName, 64); if (_tcsnicmp(rgtchClassName, _T("Volume Control"), 64) == 0) { if (!SetWindowPos(hwnd, HWND_TOP, param->x, param->y, 0, 0, SWP_NOSIZE)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetWindowPos failed, code: 0x%x", GetLastError()); } else { param->fMoved = TRUE; } } return FALSE; } return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetDeviceFlags"
void CSupervisorInfo::SetDeviceFlags( DWORD dwFlags ) { m_dwDeviceFlags = dwFlags; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetDeviceFlags"
void CSupervisorInfo::GetDeviceFlags( DWORD *pdwFlags ) { *pdwFlags = m_dwDeviceFlags; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::LaunchWindowsVolumeControl"
HRESULT CSupervisorInfo::LaunchWindowsVolumeControl(HWND hwndWizard, BOOL fRecord) { DPF_ENTER();
STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO);
TCHAR ptcharCommand[64]; PROCESS_INFORMATION* lppi; UINT uiPlayMixerID = 0; UINT uiCaptureMixerID = 0; MMRESULT mmr = MMSYSERR_NOERROR; mmr = mixerGetID( (HMIXEROBJ) (UINT_PTR) m_uiWaveInDeviceId, &uiCaptureMixerID, MIXER_OBJECTF_WAVEIN );
if( mmr != MMSYSERR_NOERROR ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to get capture mixerline mmr=0x%x", mmr ); return DV_OK; } mmr = mixerGetID( (HMIXEROBJ) (UINT_PTR) m_uiWaveOutDeviceId, &uiPlayMixerID, MIXER_OBJECTF_WAVEOUT );
if( mmr != MMSYSERR_NOERROR ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to get playback mixerline mmr=0x%x", mmr ); return DV_OK; }
if (fRecord) { _stprintf(ptcharCommand, _T("sndvol32 /R /D %i"), uiCaptureMixerID); lppi = &m_piSndVol32Record; } else { _stprintf(ptcharCommand, _T("sndvol32 /D %i"), uiPlayMixerID); lppi = &m_piSndVol32Playback; }
if (lppi->hProcess != NULL) { DWORD dwExitCode; if (GetExitCodeProcess(lppi->hProcess, &dwExitCode) != 0) { if (dwExitCode == STILL_ACTIVE) { // not dead yet! Don't start another copy,
// but do bring it to the foreground.
SMoveWindowEnumProcParam param; param.lppi = lppi; param.fMoved = FALSE; param.x = 0; param.y = 0; EnumWindows(BringToForegroundWindowEnumProc, (LPARAM)¶m); DPF_EXIT(); return DV_OK; } // The user terminated the process. Close our handles,
// and zero the process information structure
CloseHandle(lppi->hProcess); CloseHandle(lppi->hThread); ZeroMemory(lppi, sizeof(PROCESS_INFORMATION)); } else { // If GetExitCodeProcess fails, assume the handle
// is bad for some reason. Log it, then behave as
// if the process was shut down. At worst, we'll
// have multiple copies of SndVol32 running around.
Diagnostics_Write(DVF_ERRORLEVEL, "GetExitCodeProcess failed, code:0x%x", GetLastError()); // Don't close the handles, they may be bad. If they're
// not, the OS will clean 'em up when the wizard exits.
ZeroMemory(lppi, sizeof(PROCESS_INFORMATION)); } }
if (lppi->hProcess == NULL) { CreateProcess( NULL, ptcharCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, lppi);
DPFX(DPFPREP, DVF_INFOLEVEL, "Launched volume control, pid:%i", lppi->dwProcessId); // Find main window for the process we just created and
// move it manually.
//
// Note the race condition - I have no reliable way to wait until
// the main window has been displayed. So, the work around
// (a.k.a. HACK) is to keep looking for it for a while.
// If it hasn't been found by then, we just give up. It's not
// tragic if we don't find it, it just won't be as neat and
// tidy, since the window will come up wherever it was last time.
//
// Note that sndvol32.exe does not accept the STARTF_USEPOSITION
// flag on the PROCESS_INFORMATION structure, so I have to do
// this hack.
//
// In an attempt to let the sndvol32.exe get up and running,
// I call Sleep to relinquish my timeslice.
Sleep(0);
RECT rect; if (GetWindowRect(hwndWizard, &rect)) { SMoveWindowEnumProcParam param; param.lppi = lppi; param.fMoved = FALSE;
param.x = rect.left; param.y = rect.top;
int iOffset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYBORDER); if (m_piSndVol32Record.hProcess == lppi->hProcess) { // This is the recording control. Cascade it
// one level down from the wizard main window.
param.x += iOffset; param.y += iOffset; } else { // This is the playback control. Cascade it
// two levels down from the wizard main window.
param.x += iOffset*2; param.y += iOffset*2; }
// Make twenty attempts to move the window.
// Combined with Sleep(25), this will not
// wait for more than 1/2 second before giving up.
for (int i = 0; i < 20; ++i) { EnumWindows(MoveWindowEnumProc, (LPARAM)¶m); if (param.fMoved) { // window was moved, break out.
break; }
// Window was not moved. Wait 25 milliseconds (plus change)
// and try again.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Attempt to move sndvol32 window failed"); Sleep(25); } } else { Diagnostics_Write(DVF_ERRORLEVEL, "GetWindowRect failed"); } } DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CloseWindowEnumProc"
BOOL CALLBACK CloseWindowEnumProc(HWND hwnd, LPARAM lParam) { DWORD dwProcessId; DPFX(DPFPREP, DVF_INFOLEVEL, "looking for pid: 0x%p to shutdown", lParam); GetWindowThreadProcessId(hwnd, &dwProcessId); DPFX(DPFPREP, DVF_INFOLEVEL, "window: 0x%p has pid: 0x%08x", hwnd, dwProcessId); if (dwProcessId == (DWORD)lParam) { // found it, ask it to close.
DPFX(DPFPREP, DVF_INFOLEVEL, "Sending WM_CLOSE to 0x%p", hwnd); SendMessage(hwnd, WM_CLOSE, 0, 0); return FALSE; } return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CloseWindowsVolumeControl"
HRESULT CSupervisorInfo::CloseWindowsVolumeControl(BOOL fRecord) { DPF_ENTER();
PROCESS_INFORMATION* lppi;
if (fRecord) { lppi = &m_piSndVol32Record; } else { lppi = &m_piSndVol32Playback; }
if (lppi->hProcess != NULL) { DWORD dwExitCode; if (GetExitCodeProcess(lppi->hProcess, &dwExitCode) != 0) { if (dwExitCode == STILL_ACTIVE) { DPFX(DPFPREP, DVF_INFOLEVEL, "Attempting to close volume control with pid: %i", lppi->dwProcessId);
// there is currently a volume control showing, find it and
// ask it to close
EnumWindows(CloseWindowEnumProc, lppi->dwProcessId);
// Zero out the process information struct
ZeroMemory(lppi, sizeof(PROCESS_INFORMATION)); } } } DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetWaveOutVolume"
HRESULT CSupervisorInfo::GetWaveOutVolume(DWORD* lpdwVolume) { DPF_ENTER();
if (!(m_woCaps.dwSupport & WAVECAPS_VOLUME|WAVECAPS_LRVOLUME)) { // doesn't support wave out
Diagnostics_Write(DVF_ERRORLEVEL, "Wave device %i does not support volume control", m_uiWaveOutDeviceId); DPF_EXIT(); return E_FAIL; } MMRESULT mmr = waveOutGetVolume((HWAVEOUT) ((UINT_PTR) m_uiWaveOutDeviceId ), lpdwVolume); if (mmr != MMSYSERR_NOERROR) { Diagnostics_Write(DVF_ERRORLEVEL, "waveOutGetVolume failed, code: %i", mmr); DPF_EXIT(); return E_FAIL; }
if (m_woCaps.dwSupport & WAVECAPS_LRVOLUME) { // has a left and right volume control - average them
*lpdwVolume = (HIWORD(*lpdwVolume) + LOWORD(*lpdwVolume))/2; } else { // just a mono control - only the low word is significant
*lpdwVolume = LOWORD(*lpdwVolume); }
DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetWaveOutVolume"
HRESULT CSupervisorInfo::SetWaveOutVolume(DWORD dwVolume) { DPF_ENTER();
MMRESULT mmr = waveOutSetVolume((HWAVEOUT) ((UINT_PTR) m_uiWaveOutDeviceId), LOWORD(dwVolume)<<16|LOWORD(dwVolume)); if (mmr != MMSYSERR_NOERROR) { DPF_EXIT(); return E_FAIL; } DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetRecordVolume"
HRESULT CSupervisorInfo::SetRecordVolume(LONG lVolume) { HRESULT hr; DVCLIENTCONFIG dvcc; dvcc.dwSize = sizeof(dvcc); if (m_lpdpvc != NULL) { hr = m_lpdpvc->GetClientConfig(&dvcc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "GetClientConfig failed, hr:%i", hr); return hr; } dvcc.lRecordVolume = lVolume; hr = m_lpdpvc->SetClientConfig(&dvcc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetClientConfig failed, hr:%i", hr); return hr; } } else { return DVERR_INVALIDPOINTER; }
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CancelFullDuplexTest"
HRESULT CSupervisorInfo::CancelFullDuplexTest() { HRESULT hrFnc; HRESULT hr; DWORD dwRet; LONG lRet;
hrFnc = DV_OK;
Diagnostics_Write(DVF_ERRORLEVEL,"User cancelled wizard during full duplex test." );
DNEnterCriticalSection(&m_csLock); // Are we currently in the middle of a full duplex test?
if (m_hFullDuplexThread != NULL) { // This flag is periodically checked by the full duplex test
// while it works.
m_fAbortFullDuplex = TRUE;
// wait for the full duplex thread to exit gracefully
DNLeaveCriticalSection(&m_csLock); dwRet = WaitForMultipleObjects( 1, &m_hFullDuplexThread, FALSE, gc_dwLoopbackTestThreadTimeout); switch (dwRet) { case WAIT_OBJECT_0: // the full duplex thread is now done, so continue...
DNEnterCriticalSection(&m_csLock); break;
case WAIT_TIMEOUT: // The full duplex thread is not cooperating - get tough with it.
DNEnterCriticalSection(&m_csLock); hr = m_sipc.TerminateChildProcesses(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "TerminateChildProcesses failed, code: 0x%x", hr); hrFnc = hr; } if (!TerminateThread(m_hFullDuplexThread, hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "TerminateThread failed, code: 0x%x", lRet); hrFnc = DVERR_GENERIC; } break;
default: // this is not supposed to happen. Note it, terminate everything,
// and continue.
DNEnterCriticalSection(&m_csLock); if (dwRet == WAIT_ABANDONED) { Diagnostics_Write(DVF_ERRORLEVEL, "WaitForSingleObject abandoned unexpectedly"); hrFnc = DVERR_GENERIC; } else { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "WaitForSingleObject failed, code: 0x%x", lRet); hrFnc = DVERR_GENERIC; } hr = m_sipc.TerminateChildProcesses(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "TerminateChildProcesses failed, code: 0x%x", hr); hrFnc = hr; } if (!TerminateThread(m_hFullDuplexThread, hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "TerminateThread failed, code: 0x%x", lRet); hrFnc = DVERR_GENERIC; } break; }
// Close the full duplex thread handle
hr = WaitForFullDuplexThreadExitCode(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "WaitForFullDuplexThreadExitCode failed, code: 0x%x", hr); hrFnc = hr; }
// cleanup the IPC objects
hr = DeinitIPC(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DeinitIPC failed, code: 0x%x", hr); hrFnc = hr; } }
DNLeaveCriticalSection(&m_csLock); return hrFnc; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CancelLoopbackTest"
HRESULT CSupervisorInfo::CancelLoopbackTest() { HRESULT hr = DV_OK;
Diagnostics_Write(DVF_ERRORLEVEL,"User cancelled wizard during loopback test" ); DNEnterCriticalSection(&m_csLock); // Are we currently in the middle of a loopback test?
if (m_hLoopbackThread != NULL) { // If the loopback thread handle is not null, the mic test may still
// be going on, in which case we want to set that flag to
// REGVAL_NOTRUN, since the test was not completed.
DWORD dwRegVal; GetMicDetected(&dwRegVal); if (dwRegVal == REGVAL_CRASHED) { SetMicDetected(REGVAL_NOTRUN); } DNLeaveCriticalSection(&m_csLock); // ShutdownLoopbackThread has its own guard
hr = ShutdownLoopbackThread(); DNEnterCriticalSection(&m_csLock); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, code: %i", hr); } }
DNLeaveCriticalSection(&m_csLock);
return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::Cancel"
HRESULT CSupervisorInfo::Cancel() { DPF_ENTER(); DWORD dwRet; HRESULT hr; LONG lRet; HRESULT hrFnc; BOOL fDone; BOOL fGotMsg; BOOL fWelcomeNext; MSG msg;
DNEnterCriticalSection(&m_csLock);
hrFnc = DV_OK;
// close any open volume controls
CloseWindowsVolumeControl(TRUE); CloseWindowsVolumeControl(FALSE);
// The cancel button can be hit at any time.
// We are not in a known state. This function
// has to figure it out from the member variables.
// How fun.
DNLeaveCriticalSection(&m_csLock); // CancelFullDuplexTest has it's own guard
hrFnc = CancelFullDuplexTest(); DNEnterCriticalSection(&m_csLock); // Are we currently in the middle of a loopback test?
if (m_hLoopbackThread != NULL) { DNLeaveCriticalSection(&m_csLock); // ShutdownLoopbackThread has its own guard
hr = ShutdownLoopbackThread(); DNEnterCriticalSection(&m_csLock); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, code: %i", hr); hrFnc = hr; } }
// Reset the registry to the "test not yet run" state
// but only if the user moved past the welcome page
GetWelcomeNext(&fWelcomeNext); if (fWelcomeNext) { hr = SetHalfDuplex(REGVAL_NOTRUN); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetHalfDuplex failed, code: %i", hr); hrFnc = hr; }
hr = SetFullDuplex(REGVAL_NOTRUN); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetFullDuplex failed, code: %i", hr); hrFnc = hr; }
hr = SetMicDetected(REGVAL_NOTRUN); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetMicDetected failed, code: %i", hr); hrFnc = hr; } }
// record the fact that the wizard was bailed out of
SetUserCancel(); DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hrFnc; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::Abort"
HRESULT CSupervisorInfo::Abort(HWND hDlg, HRESULT hrDlg) { // This is the function called whenever a fatal error is hit while in the wizard
DPF_ENTER(); DWORD dwRet; HRESULT hr; LONG lRet; HRESULT hrFnc; BOOL fDone; BOOL fGotMsg; BOOL fWelcomeNext; MSG msg; HWND hwndParent = NULL;
hrFnc = DV_OK;
// close any open volume controls
DNEnterCriticalSection(&m_csLock); CloseWindowsVolumeControl(TRUE); CloseWindowsVolumeControl(FALSE); DNLeaveCriticalSection(&m_csLock);
// The cancel button can be hit at any time.
// We are not in a known state. This function
// has to figure it out from the member variables.
// How fun.
// CancelFullDuplexTest has it's own guard
hrFnc = CancelFullDuplexTest(); // Are we currently in the middle of a loopback test?
DNEnterCriticalSection(&m_csLock); if (m_hLoopbackThread != NULL) { DNLeaveCriticalSection(&m_csLock); // ShutdownLoopbackThread has its own guard
hr = ShutdownLoopbackThread(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, code: %i", hr); hrFnc = hr; } }
// Leave the registry alone - this will signal that there was
// an error to the next wizard run, assuming we're still in
// the middle of a test. If we've actually gotten far enough
// along to record a pass in the registry, so be it.
// Call EndDialog to forcibly bail out of the wizard.
Diagnostics_Write(DVF_ERRORLEVEL, "Attempting to abort wizard, hr: %i", hrDlg); hwndParent = GetParent(hDlg); if (IsWindow(hwndParent)) { PostMessage(hwndParent, WM_CLOSE, (WPARAM)NULL, (LPARAM)NULL); /*
// EndDialog does not work because we are in a property sheet
if (!EndDialog(hwndParent, hrDlg)) { Diagnostics_Write(DVF_ERRORLEVEL, "EndDialog failed, code: %i:", GetLastError()); } */ } else { Diagnostics_Write(DVF_ERRORLEVEL, "Unable to get a handle to the wizard!"); } DPF_EXIT(); return hrFnc; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::Finish"
HRESULT CSupervisorInfo::Finish() { DPF_ENTER();
DWORD dwRet; HRESULT hr; LONG lRet; HRESULT hrFnc; DWORD dwValue; DNEnterCriticalSection(&m_csLock);
hrFnc = DV_OK;
// close any open volume controls
CloseWindowsVolumeControl(TRUE); CloseWindowsVolumeControl(FALSE);
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hrFnc; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CreateFullDuplexThread"
HRESULT CSupervisorInfo::CreateFullDuplexThread() { DPF_ENTER(); HRESULT hr; LONG lRet; DWORD dwThreadId; DNEnterCriticalSection(&m_csLock);
// Null out the interface pointer
m_lpdpvc = NULL;
if (m_hFullDuplexThread != NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "m_hFullDuplexThread not NULL"); hr = DVERR_GENERIC; goto error_cleanup; } m_hFullDuplexThread = CreateThread(NULL, 0, FullDuplexTestThreadProc, (LPVOID)this, NULL, &dwThreadId); if (m_hFullDuplexThread == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreateThread failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::WaitForFullDuplexThreadExitCode"
HRESULT CSupervisorInfo::WaitForFullDuplexThreadExitCode() { DPF_ENTER(); HRESULT hr; HRESULT hrFnc; LONG lRet; DWORD dwThreadId; DWORD dwRet; DNEnterCriticalSection(&m_csLock);
if (m_hFullDuplexThread == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "m_hFullDuplexThread is NULL"); hr = DVERR_GENERIC; goto error_cleanup; }
dwRet = WaitForSingleObject(m_hFullDuplexThread, gc_dwChildWaitTimeout); switch(dwRet) { case WAIT_OBJECT_0: break;
case WAIT_TIMEOUT: Diagnostics_Write(DVF_ERRORLEVEL, "Timed out waiting for full duplex test thread to exit - terminating forcibly"); TerminateThread(m_hFullDuplexThread, DVERR_GENERIC); hr = DVERR_GENERIC; goto error_cleanup;
default: Diagnostics_Write(DVF_ERRORLEVEL, "Unknown error waiting for full duplex test thread to exit - terminating forcibly"); TerminateThread(m_hFullDuplexThread, DVERR_GENERIC); hr = DVERR_GENERIC; goto error_cleanup; }
if (!GetExitCodeThread(m_hFullDuplexThread, (DWORD*)&hrFnc)) { Diagnostics_Write(DVF_ERRORLEVEL, "Error retrieving full duplex test thread's exit code"); hr = DVERR_GENERIC; goto error_cleanup; } if (!CloseHandle(m_hFullDuplexThread)) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } m_hFullDuplexThread = NULL;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hrFnc;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CreateLoopbackThread"
HRESULT CSupervisorInfo::CreateLoopbackThread() { DPF_ENTER(); HRESULT hr; LONG lRet; DWORD dwThreadId; DNEnterCriticalSection(&m_csLock); m_hLoopbackShutdownEvent = NULL;
if (m_hLoopbackThread != NULL) { // The loopback test is already running.
// Just dump a warning and return pending.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "m_hLoopbackThread not NULL"); hr = DVERR_PENDING; goto error_cleanup; }
// create an event the loopback thread signals just before it exits
m_hLoopbackThreadExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hLoopbackThreadExitEvent == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreateEvent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// create an event the loopback thread listens for to shutdown
m_hLoopbackShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hLoopbackShutdownEvent == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreateEvent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_hLoopbackThread = CreateThread(NULL, 0, LoopbackTestThreadProc, (LPVOID)this, NULL, &dwThreadId); if (m_hLoopbackThread == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreateThread failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: if (m_hLoopbackThreadExitEvent != NULL) { CloseHandle(m_hLoopbackThreadExitEvent); m_hLoopbackThreadExitEvent = NULL; } if (m_hLoopbackShutdownEvent != NULL) { CloseHandle(m_hLoopbackShutdownEvent); m_hLoopbackShutdownEvent = NULL; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::WaitForLoopbackShutdownEvent"
HRESULT CSupervisorInfo::WaitForLoopbackShutdownEvent() { DPF_ENTER(); HRESULT hr; LONG lRet; DWORD dwThreadId; DWORD dwRet; HANDLE hEvent; DNEnterCriticalSection(&m_csLock); hEvent = m_hLoopbackShutdownEvent; DNLeaveCriticalSection(&m_csLock); dwRet = WaitForSingleObject(hEvent, INFINITE); DNEnterCriticalSection(&m_csLock); switch (dwRet) { case WAIT_OBJECT_0: // expected behavior, continue
break; case WAIT_TIMEOUT: Diagnostics_Write(DVF_ERRORLEVEL, "WaitForSingleObject timed out unexpectedly"); hr = DVERR_GENERIC; goto error_cleanup; case WAIT_ABANDONED: Diagnostics_Write(DVF_ERRORLEVEL, "WaitForSingleObject abandoned unexpectedly"); hr = DVERR_GENERIC; goto error_cleanup;
default: lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "WaitForSingleObject returned unknown code, GetLastError(): %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SignalLoopbackThreadDone"
HRESULT CSupervisorInfo::SignalLoopbackThreadDone() { DPF_ENTER(); HRESULT hr; LONG lRet; HANDLE hEvent;
DNEnterCriticalSection(&m_csLock); hEvent = m_hLoopbackThreadExitEvent; DNLeaveCriticalSection(&m_csLock); if (!SetEvent(hEvent)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "SetEvent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } DPF_EXIT(); return DV_OK;
error_cleanup: DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ShutdownLoopbackThread"
HRESULT CSupervisorInfo::ShutdownLoopbackThread() { DPF_ENTER(); HRESULT hr; LONG lRet; DWORD dwThreadId; DWORD dwRet; BOOL fDone; BOOL fGotMsg; MSG msg; HANDLE rghHandle[2]; HANDLE hEvent;
DNEnterCriticalSection(&m_csLock);
if (m_hLoopbackThread == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "m_hLoopbackThread is NULL"); hr = DVERR_GENERIC; goto error_cleanup; }
if (!SetEvent(m_hLoopbackShutdownEvent)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "SetEvent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
/*
rghHandle[0] = m_hLoopbackThreadExitEvent; rghHandle[1] = m_hLoopbackThread; */ hEvent = m_hLoopbackThreadExitEvent;
DNLeaveCriticalSection(&m_csLock); fDone = FALSE; while (!fDone) { dwRet = WaitForSingleObject(hEvent, gc_dwLoopbackTestThreadTimeout); switch(dwRet) { case WAIT_OBJECT_0: DNEnterCriticalSection(&m_csLock); fDone = TRUE; break;
case WAIT_ABANDONED: default: // not supposed to be possible, but treat both like a timeout.
case WAIT_TIMEOUT: DNEnterCriticalSection(&m_csLock); hr = DVERR_TIMEOUT; goto error_cleanup; break; } /*
dwRet = MsgWaitForMultipleObjects(2, rghHandle, FALSE, gc_dwLoopbackTestThreadTimeout, QS_ALLINPUT); switch (dwRet) { case WAIT_OBJECT_0: case WAIT_OBJECT_0 + 1: // expected result, continue...
DNEnterCriticalSection(&m_csLock); fDone = TRUE; break; case WAIT_TIMEOUT: // loopback thread is not behaving, jump to
// the error block where it will be terminated forcibly
DNEnterCriticalSection(&m_csLock); hr = DVERR_TIMEOUT; goto error_cleanup; break;
case WAIT_OBJECT_0 + 2: // One or more windows messages have been posted to this thread's
// message queue. Deal with 'em.
fGotMsg = TRUE; while( fGotMsg ) { fGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
if( fGotMsg ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } break;
default: if (dwRet == WAIT_ABANDONED) { Diagnostics_Write(DVF_ERRORLEVEL, "MsgWaitForMultipleObjects abandoned unexpectedly"); } else { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "MsgWaitForMultipleObjects failed, code: %i"); } DNEnterCriticalSection(&m_csLock); hr = DVERR_TIMEOUT; goto error_cleanup; break; } */ }
if (!CloseHandle(m_hLoopbackThread)) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); m_hLoopbackThread = NULL; hr = DVERR_GENERIC; goto error_cleanup; } m_hLoopbackThread = NULL;
if (!CloseHandle(m_hLoopbackThreadExitEvent)) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); m_hLoopbackThreadExitEvent = NULL; hr = DVERR_GENERIC; goto error_cleanup; } m_hLoopbackThreadExitEvent = NULL;
if (!CloseHandle(m_hLoopbackShutdownEvent)) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); m_hLoopbackShutdownEvent = NULL; hr = DVERR_GENERIC; goto error_cleanup; } m_hLoopbackShutdownEvent = NULL; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: if (m_hLoopbackThread != NULL) { TerminateThread(m_hLoopbackThread, DVERR_GENERIC); CloseHandle(m_hLoopbackThread); m_hLoopbackThread = NULL; }
if (m_hLoopbackThreadExitEvent != NULL) { CloseHandle(m_hLoopbackThreadExitEvent); m_hLoopbackThreadExitEvent = NULL; } if (m_hLoopbackShutdownEvent != NULL) { CloseHandle(m_hLoopbackShutdownEvent); m_hLoopbackShutdownEvent = NULL; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetFullDuplex"
HRESULT CSupervisorInfo::SetFullDuplex(DWORD dwFullDuplex) { DPF_ENTER(); HRESULT hr = DV_OK; HKEY hk; LONG lRet; DNEnterCriticalSection(&m_csLock);
if (!m_creg.WriteDWORD(gc_wszValueName_FullDuplex, dwFullDuplex)) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::WriteDWORD failed"); hr = DVERR_GENERIC; } else { // Flush the registry operations to ensure they
// are written. Otherwise we may not detect a crash!
hk = m_creg.GetHandle(); lRet = RegFlushKey(hk); if (lRet != ERROR_SUCCESS) { Diagnostics_Write(DVF_ERRORLEVEL, "RegFlushKey failed"); hr = DVERR_GENERIC; } }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetFullDuplex"
HRESULT CSupervisorInfo::GetFullDuplex(DWORD* pdwFullDuplex) { DPF_ENTER(); HRESULT hr = DV_OK; DNEnterCriticalSection(&m_csLock);
if (!m_creg.ReadDWORD(gc_wszValueName_FullDuplex, *pdwFullDuplex)) { // registry key is not present
*pdwFullDuplex = 0; hr = DVERR_GENERIC; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHalfDuplex"
HRESULT CSupervisorInfo::SetHalfDuplex(DWORD dwHalfDuplex) { DPF_ENTER(); HRESULT hr = DV_OK; LONG lRet; HKEY hk; DNEnterCriticalSection(&m_csLock);
if (!m_creg.WriteDWORD(gc_wszValueName_HalfDuplex, dwHalfDuplex)) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::WriteDWORD failed"); hr = DVERR_GENERIC; } else { // Flush the registry operations to ensure they
// are written. Otherwise we may not detect a crash!
hk = m_creg.GetHandle(); lRet = RegFlushKey(hk); if (lRet != ERROR_SUCCESS) { Diagnostics_Write(DVF_ERRORLEVEL, "RegFlushKey failed"); hr = DVERR_GENERIC; } }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHalfDuplex"
HRESULT CSupervisorInfo::GetHalfDuplex(DWORD* pdwHalfDuplex) { DPF_ENTER(); HRESULT hr = DV_OK; DNEnterCriticalSection(&m_csLock);
if (!m_creg.ReadDWORD(gc_wszValueName_HalfDuplex, *pdwHalfDuplex)) { // registry key is not present
*pdwHalfDuplex = 0; hr = DVERR_GENERIC; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetMicDetected"
HRESULT CSupervisorInfo::SetMicDetected(DWORD dwMicDetected) { DPF_ENTER(); HRESULT hr = DV_OK; LONG lRet; HKEY hk;
DNEnterCriticalSection(&m_csLock);
if (!m_creg.WriteDWORD(gc_wszValueName_MicDetected, dwMicDetected)) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::WriteDWORD failed"); hr = DVERR_GENERIC; } else { // Flush the registry operations to ensure they
// are written. Otherwise we may not detect a crash!
hk = m_creg.GetHandle(); lRet = RegFlushKey(hk); if (lRet != ERROR_SUCCESS) { Diagnostics_Write(DVF_ERRORLEVEL, "RegFlushKey failed"); hr = DVERR_GENERIC; } }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetMicDetected"
HRESULT CSupervisorInfo::GetMicDetected(DWORD* pdwMicDetected) { DPF_ENTER(); HRESULT hr = DV_OK; DNEnterCriticalSection(&m_csLock);
if (!m_creg.ReadDWORD(gc_wszValueName_MicDetected, *pdwMicDetected)) { // registry key is not present
*pdwMicDetected = 0; hr = DVERR_GENERIC; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::QueryFullDuplex"
HRESULT CSupervisorInfo::QueryFullDuplex() { DPF_ENTER(); HRESULT hr; DWORD dwFullDuplex; DWORD dwHalfDuplex; DWORD dwMicDetected; DNEnterCriticalSection(&m_csLock);
if (!m_creg.ReadDWORD(gc_wszValueName_HalfDuplex, dwHalfDuplex)) { // registry key is not present - setup has not run
DPFX(DPFPREP, DVF_WARNINGLEVEL, "HalfDuplex key not found in registry"); hr = DVERR_RUNSETUP; goto error_cleanup; } switch (dwHalfDuplex) { case REGVAL_NOTRUN: // test not run
DPFX(DPFPREP, DVF_WARNINGLEVEL, "HalfDuplex = 0; test not run"); hr = DVERR_RUNSETUP; goto error_cleanup; case REGVAL_CRASHED: // test crashed out!
DPFX(DPFPREP, DVF_WARNINGLEVEL, "HalfDuplex = 1; test crashed"); hr = DVERR_SOUNDINITFAILURE; goto error_cleanup;
case REGVAL_FAILED: // test failed gracefully
DPFX(DPFPREP, DVF_WARNINGLEVEL, "HalfDuplex = 2; test failed gracefully"); hr = DVERR_SOUNDINITFAILURE; goto error_cleanup; case REGVAL_PASSED: // test passed
DPFX(DPFPREP, DVF_INFOLEVEL, "HalfDuplex = 3; test passed"); break;
default: // bad key value - return run setup
DPFX(DPFPREP, DVF_WARNINGLEVEL, "HalfDuplex = %i; bad key value!", dwHalfDuplex); hr = DVERR_RUNSETUP; goto error_cleanup; }
if (!m_creg.ReadDWORD(gc_wszValueName_FullDuplex, dwFullDuplex)) { // registry key is not present - very odd.
// however, since we at least passed half duplex to get
// here, we'll return half duplex
DPFX(DPFPREP, DVF_WARNINGLEVEL, "FullDuplex key not found in registry"); hr = DV_HALFDUPLEX; goto error_cleanup; } switch (dwFullDuplex) { case REGVAL_NOTRUN: // Test not run - this is very odd, considering that
// in order to get here, the half duplex test must have
// been run and passed. Return half duplex.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "FullDuplex = 0; test not run"); hr = DV_HALFDUPLEX; goto error_cleanup; case REGVAL_CRASHED: // test crashed out! - They tried, and going further
// wouldn't help, so certify them for half duplex
DPFX(DPFPREP, DVF_WARNINGLEVEL, "FullDuplex = 1; test crashed"); hr = DV_HALFDUPLEX; goto error_cleanup;
case REGVAL_FAILED: // test failed gracefully - mic test would not have been
// run, certify them for half duplex.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "FullDuplex = 2; test failed gracefully"); hr = DV_HALFDUPLEX; goto error_cleanup; case REGVAL_PASSED: // test passed
DPFX(DPFPREP, DVF_INFOLEVEL, "FullDuplex = 3; test passed"); break;
default: // bad key value - but the system can at least do
// half duplex, so certify them for half duplex
DPFX(DPFPREP, DVF_WARNINGLEVEL, "FullDuplex = %i; bad key value!", dwFullDuplex); hr = DV_HALFDUPLEX; goto error_cleanup; }
// From this point on, we know the full duplex test was ok.
// However, in order to get a full duplex pass, the mic must
// also have been detected.
if (!m_creg.ReadDWORD(gc_wszValueName_MicDetected, dwMicDetected)) { // registry key is not present - very odd
DPFX(DPFPREP, DVF_WARNINGLEVEL, "MicDetected key not found in registry"); hr = DV_HALFDUPLEX; goto error_cleanup; } switch (dwMicDetected) { case REGVAL_NOTRUN: // Test not run - odd, but pass them for half duplex anyway
DPFX(DPFPREP, DVF_WARNINGLEVEL, "MicDetected = 0; test not run"); hr = DV_HALFDUPLEX; goto error_cleanup; case REGVAL_CRASHED: // test crashed out! This shouldn't happen, since it
// should have been caught in the full duplex test,
// but either way, they tried thier best and half
// duplex worked, so certify them for half duplex.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "MicDetected = 1; test crashed"); hr = DV_HALFDUPLEX; goto error_cleanup;
case REGVAL_FAILED: // test failed gracefully - certify for half duplex
DPFX(DPFPREP, DVF_WARNINGLEVEL, "MicDetected = 2; test failed gracefully"); hr = DV_HALFDUPLEX; goto error_cleanup; case REGVAL_PASSED: // test passed
DPFX(DPFPREP, DVF_INFOLEVEL, "MicDetected = 3; test passed"); break;
default: // bad key value - odd, but pass them for half duplex anyway.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "MicDetected = %i; bad key value!", dwMicDetected); hr = DV_HALFDUPLEX; goto error_cleanup; }
// If we get here, all keys were a clean pass, so return full duplex
hr = DV_FULLDUPLEX;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::OpenRegKey"
HRESULT CSupervisorInfo::OpenRegKey(BOOL fCreate) { DPF_ENTER(); LONG lRet; HRESULT hr; CRegistry cregAudioConfig; HKEY hkAudioConfig; CRegistry cregRender; HKEY hkRender; WCHAR wszRenderGuidString[GUID_STRING_LEN]; WCHAR wszCaptureGuidString[GUID_STRING_LEN]; BOOL bAudioKeyOpen = FALSE; BOOL bRenderKeyOpen = FALSE; DNEnterCriticalSection(&m_csLock);
if (!cregAudioConfig.Open(HKEY_CURRENT_USER, gc_wszKeyName_AudioConfig, FALSE, fCreate)) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::Open failed"); hr = DVERR_GENERIC; goto error_cleanup; } bAudioKeyOpen = TRUE;
hkAudioConfig = cregAudioConfig.GetHandle(); if (!cregRender.Open(hkAudioConfig, &m_guidRenderDevice, FALSE, fCreate)) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::Open failed"); hr = DVERR_GENERIC; goto error_cleanup; } bRenderKeyOpen = TRUE;
hkRender = cregRender.GetHandle(); if (!m_creg.Open(hkRender, &m_guidCaptureDevice, FALSE, fCreate)) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::Open failed"); hr = DVERR_GENERIC; goto error_cleanup; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK;
error_cleanup: if (bRenderKeyOpen) { cregRender.Close(); }
if (bAudioKeyOpen) { cregAudioConfig.Close(); }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ThereCanBeOnlyOne"
HRESULT CSupervisorInfo::ThereCanBeOnlyOne() { DPF_ENTER(); LONG lRet; HANDLE hMutex; HRESULT hr; hr = DV_OK; hMutex = CreateMutex(NULL, FALSE, gc_szMutexName); lRet = GetLastError(); if (hMutex == NULL) { // something went very wrong
Diagnostics_Write(DVF_ERRORLEVEL, "CreateMutex failed, code: %i", lRet); return DVERR_GENERIC; } // see if the mutex already existed
if (lRet == ERROR_ALREADY_EXISTS) { Diagnostics_Write(DVF_ERRORLEVEL, "Detected another instance of test running"); if (!CloseHandle(hMutex)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); } return DVERR_ALREADYPENDING; }
DNEnterCriticalSection(&m_csLock); if (m_hMutex != NULL) { DNLeaveCriticalSection(&m_csLock); Diagnostics_Write(DVF_ERRORLEVEL, "m_hMutex not null"); if (!CloseHandle(hMutex)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); } return DVERR_GENERIC; }
m_hMutex = hMutex;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CloseMutex"
void CSupervisorInfo::CloseMutex() { DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
LONG lRet; // close the mutex
if (!CloseHandle(m_hMutex)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CloseHandle failed, code: %i", lRet); } m_hMutex = NULL;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetVoiceDetected"
void CSupervisorInfo::SetVoiceDetected() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fVoiceDetected = TRUE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ClearVoiceDetected"
void CSupervisorInfo::ClearVoiceDetected() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fVoiceDetected = FALSE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetVoiceDetected"
void CSupervisorInfo::GetVoiceDetected(BOOL* lpfPreviousCrash) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lpfPreviousCrash = m_fVoiceDetected; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetUserBack"
void CSupervisorInfo::SetUserBack() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fUserBack = TRUE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ClearUserBack"
void CSupervisorInfo::ClearUserBack() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fUserBack = FALSE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetUserBack"
void CSupervisorInfo::GetUserBack(BOOL* lpfUserBack) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lpfUserBack = m_fUserBack; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetUserCancel"
void CSupervisorInfo::SetUserCancel() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fUserCancel = TRUE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ClearUserCancel"
void CSupervisorInfo::ClearUserCancel() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fUserCancel = FALSE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetUserCancel"
void CSupervisorInfo::GetUserCancel(BOOL* lpfUserCancel) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lpfUserCancel = m_fUserCancel; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetWelcomeNext"
void CSupervisorInfo::SetWelcomeNext() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fWelcomeNext = TRUE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ClearWelcomeNext"
void CSupervisorInfo::ClearWelcomeNext() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fWelcomeNext = FALSE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetWelcomeNext"
void CSupervisorInfo::GetWelcomeNext(BOOL* lpfWelcomeNext) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lpfWelcomeNext = m_fWelcomeNext; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetError"
void CSupervisorInfo::GetError(HRESULT* hr) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *hr = m_hrError; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetError"
void CSupervisorInfo::SetError(HRESULT hr) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hrError = hr; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetTitleFont"
void CSupervisorInfo::GetTitleFont(HFONT* lphfTitle) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphfTitle = m_hfTitle; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetBoldFont"
void CSupervisorInfo::GetBoldFont(HFONT* lphfBold) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphfBold = m_hfBold; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetCaptureDevice"
void CSupervisorInfo::GetCaptureDevice(GUID* lpguidCaptureDevice) { DPFX(DPFPREP, DVF_ENTRYLEVEL, "Enter"); DNEnterCriticalSection(&m_csLock); *lpguidCaptureDevice = m_guidCaptureDevice; DNLeaveCriticalSection(&m_csLock); DPFX(DPFPREP, DVF_ENTRYLEVEL, "Exit"); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetCaptureDevice"
void CSupervisorInfo::SetCaptureDevice(GUID guidCaptureDevice) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_guidCaptureDevice = guidCaptureDevice; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetRenderDevice"
void CSupervisorInfo::GetRenderDevice(GUID* lpguidRenderDevice) { DPFX(DPFPREP, DVF_ENTRYLEVEL, "Enter"); DNEnterCriticalSection(&m_csLock); *lpguidRenderDevice = m_guidRenderDevice; DNLeaveCriticalSection(&m_csLock); DPFX(DPFPREP, DVF_ENTRYLEVEL, "Exit"); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetRenderDevice"
void CSupervisorInfo::SetRenderDevice(GUID guidRenderDevice) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_guidRenderDevice = guidRenderDevice; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetWaveOutId"
HRESULT CSupervisorInfo::SetWaveOutId(UINT ui) { HRESULT hr = DV_OK; DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_uiWaveOutDeviceId = ui;
ZeroMemory(&m_woCaps, sizeof(WAVEOUTCAPS)); MMRESULT mmr = waveOutGetDevCaps(ui, &m_woCaps, sizeof(WAVEOUTCAPS)); if (mmr != MMSYSERR_NOERROR) { ZeroMemory(&m_woCaps, sizeof(WAVEOUTCAPS)); hr = DVERR_INVALIDPARAM; }
//error_cleanup:
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetWaveInId"
void CSupervisorInfo::SetWaveInId(UINT ui) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_uiWaveInDeviceId = ui; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetLoopbackFlags"
void CSupervisorInfo::GetLoopbackFlags(DWORD* pdwFlags) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *pdwFlags = m_dwLoopbackFlags; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetLoopbackFlags"
void CSupervisorInfo::SetLoopbackFlags(DWORD dwFlags) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_dwLoopbackFlags = dwFlags; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetCheckAudioSetupFlags"
void CSupervisorInfo::GetCheckAudioSetupFlags(DWORD* pdwFlags) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *pdwFlags = m_dwCheckAudioSetupFlags; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetCheckAudioSetupFlags"
void CSupervisorInfo::SetCheckAudioSetupFlags(DWORD dwFlags) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_dwCheckAudioSetupFlags = dwFlags; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetFullDuplexResults"
void CSupervisorInfo::GetFullDuplexResults(HRESULT* phr) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *phr = m_hrFullDuplexResults; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetFullDuplexResults"
void CSupervisorInfo::SetFullDuplexResults(HRESULT hr) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hrFullDuplexResults = hr; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDParent"
void CSupervisorInfo::GetHWNDParent(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndParent; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDWizard"
void CSupervisorInfo::SetHWNDParent(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndParent = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDWizard"
void CSupervisorInfo::GetHWNDWizard(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndWizard; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDWizard"
void CSupervisorInfo::SetHWNDWizard(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndWizard = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDDialog"
void CSupervisorInfo::GetHWNDDialog(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndDialog; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDDialog"
void CSupervisorInfo::SetHWNDDialog(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndDialog = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDProgress"
void CSupervisorInfo::GetHWNDProgress(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndProgress; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDProgress"
void CSupervisorInfo::SetHWNDProgress(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndProgress = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDInputPeak"
void CSupervisorInfo::GetHWNDInputPeak(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndInputPeak; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDInputPeak"
void CSupervisorInfo::SetHWNDInputPeak(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndInputPeak = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDOutputPeak"
void CSupervisorInfo::GetHWNDOutputPeak(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndOutputPeak; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDOutputPeak"
void CSupervisorInfo::SetHWNDOutputPeak(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndOutputPeak = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDInputVolumeSlider"
void CSupervisorInfo::GetHWNDInputVolumeSlider(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndInputVolumeSlider; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDInputVolumeSlider"
void CSupervisorInfo::SetHWNDInputVolumeSlider(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndInputVolumeSlider = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetInputVolumeSliderPos"
void CSupervisorInfo::GetInputVolumeSliderPos(LONG* lpl) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lpl = m_lInputVolumeSliderPos; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetInputVolumeSliderPos"
void CSupervisorInfo::SetInputVolumeSliderPos(LONG l) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_lInputVolumeSliderPos = l; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetHWNDOutputVolumeSlider"
void CSupervisorInfo::GetHWNDOutputVolumeSlider(HWND* lphwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphwnd = m_hwndOutputVolumeSlider; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetHWNDOutputVolumeSlider"
void CSupervisorInfo::SetHWNDOutputVolumeSlider(HWND hwnd) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hwndOutputVolumeSlider = hwnd; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetDPVC"
void CSupervisorInfo::GetDPVC(LPDIRECTPLAYVOICECLIENT* lplpdpvc) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lplpdpvc = m_lpdpvc; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetDPVC"
void CSupervisorInfo::SetDPVC(LPDIRECTPLAYVOICECLIENT lpdpvc) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_lpdpvc = lpdpvc; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetLoopbackShutdownEvent"
void CSupervisorInfo::GetLoopbackShutdownEvent(HANDLE* lphEvent) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lphEvent = m_hLoopbackShutdownEvent; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::SetLoopbackShutdownEvent"
void CSupervisorInfo::SetLoopbackShutdownEvent(HANDLE hEvent) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_hLoopbackShutdownEvent = hEvent; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetIPC"
void CSupervisorInfo::GetIPC(CSupervisorIPC** lplpsipc) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lplpsipc = &m_sipc; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetAbortFullDuplex"
void CSupervisorInfo::GetAbortFullDuplex(BOOL* lpfAbort) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); *lpfAbort = m_fAbortFullDuplex; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::ClearAbortFullDuplex"
void CSupervisorInfo::ClearAbortFullDuplex() { DPF_ENTER(); DNEnterCriticalSection(&m_csLock); m_fAbortFullDuplex = FALSE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::InitIPC"
HRESULT CSupervisorInfo::InitIPC() { DPF_ENTER(); HRESULT hr;
// the IPC object has it's own guard...
hr = m_sipc.Init(); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::DeinitIPC"
HRESULT CSupervisorInfo::DeinitIPC() { DPF_ENTER(); HRESULT hr;
// The IPC object has it's own guard...
// and this is a safe call even if Init
// has not been called
hr = m_sipc.Deinit(); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::InitClass"
BOOL CSupervisorInfo::InitClass() { if (DNInitializeCriticalSection(&m_csLock)) { m_fCritSecInited = TRUE; return TRUE; } else { return FALSE; } }
#undef DPF_MODNAME
#define DPF_MODNAME "SupervisorCheckAudioSetup"
HRESULT SupervisorCheckAudioSetup( const GUID* lpguidRenderDevice, const GUID* lpguidCaptureDevice, HWND hwndParent, DWORD dwFlags) { DPF_ENTER(); HRESULT hr; LRESULT lRet; HKEY hkDevice = NULL; int iRet; CSupervisorInfo sinfo; CPeakMeterWndClass pmwc; BOOL fFullDuplexPassed; BOOL fVoiceDetected; BOOL fUserCancel; BOOL fUserBack; GUID guidCaptureDevice; GUID guidRenderDevice; BOOL fRegKeyOpen = FALSE; BOOL fWndClassRegistered = FALSE; BOOL fTitleFontCreated = FALSE; BOOL fBoldFontCreated = FALSE; BOOL fMutexOpen = FALSE;
if (!sinfo.InitClass()) { return DVERR_OUTOFMEMORY; }
// init the globals
g_hResDLLInstance = NULL;
// validate the HWND, if non null
if (hwndParent != NULL && !IsWindow(hwndParent)) { Diagnostics_Write(DVF_ERRORLEVEL, "Invalid (but non-null) Window Handle passed in CheckAudioSetup"); hr = DVERR_INVALIDPARAM; goto error_cleanup; }
// validate the flags
if (dwFlags & ~(DVFLAGS_QUERYONLY|DVFLAGS_NOQUERY|DVFLAGS_WAVEIDS|DVFLAGS_ALLOWBACK)) { Diagnostics_Write(DVF_ERRORLEVEL, "Invalid flags specified in CheckAudioSetup: %x", dwFlags); hr = DVERR_INVALIDFLAGS; goto error_cleanup; } if (dwFlags & DVFLAGS_QUERYONLY) { if (dwFlags & (DVFLAGS_NOQUERY|DVFLAGS_ALLOWBACK)) { Diagnostics_Write(DVF_ERRORLEVEL, "Invalid flags specified in CheckAudioSetup: %x", dwFlags); hr = DVERR_INVALIDFLAGS; goto error_cleanup; } }
// save the flags
sinfo.SetCheckAudioSetupFlags(dwFlags);
// if the waveid flag was specified, translate the waveid to a guid
if (dwFlags & DVFLAGS_WAVEIDS) { hr = DV_MapWaveIDToGUID( FALSE, lpguidRenderDevice->Data1, guidRenderDevice ); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DV_MapWaveIDToGUID failed, code: %i", hr); goto error_cleanup; } hr = DV_MapWaveIDToGUID( TRUE, lpguidCaptureDevice->Data1, guidCaptureDevice ); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DV_MapWaveIDToGUID failed, code: %i", hr); goto error_cleanup; } } else { hr = DV_MapPlaybackDevice(lpguidRenderDevice, &guidRenderDevice); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DV_MapPlaybackDevice failed, code: %i", hr); goto error_cleanup; }
// map the devices
hr = DV_MapCaptureDevice(lpguidCaptureDevice, &guidCaptureDevice); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DV_MapCaptureDevice failed, code: %i", hr); goto error_cleanup; } } // the device guids have been mapped, if required, so save them
sinfo.SetCaptureDevice(guidCaptureDevice); sinfo.SetRenderDevice(guidRenderDevice);
// get the device descriptions, which also validates the GUIDs on
// pre-millennium systems.
hr = sinfo.GetDeviceDescriptions(); if (FAILED(hr)) { // error, log it and bail out of the wizard
Diagnostics_Write(DVF_ERRORLEVEL, "Error getting device descriptions, code: %i", hr); goto error_cleanup; }
// Open the registry key
hr = sinfo.OpenRegKey(TRUE); if (FAILED(hr)) { // error, log it and bail out of the wizard
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to open reg key, code: %i", hr); hr = DVERR_GENERIC; goto error_cleanup; } fRegKeyOpen = TRUE; if (dwFlags & DVFLAGS_QUERYONLY) { hr = SupervisorQueryAudioSetup(&sinfo); sinfo.CloseRegKey(); DPF_EXIT(); return hr; }
g_hResDLLInstance = LoadLibraryA(gc_szResDLLName); if (g_hResDLLInstance == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "Unable to get instance handle to resource dll: %s", gc_szResDLLName); Diagnostics_Write(DVF_ERRORLEVEL, "LoadLibrary error code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// check for other instances of the wizard
hr = sinfo.ThereCanBeOnlyOne(); if (FAILED(hr)) { if (hr == DVERR_ALREADYPENDING) { Diagnostics_Write(DVF_ERRORLEVEL, "DirectPlay Voice Setup Wizard already running"); } else { Diagnostics_Write(DVF_ERRORLEVEL, "ThereCanBeOnlyOne failed, hr: %i", hr); } goto error_cleanup; } fMutexOpen = TRUE; // register the peak meter custom control window class
hr = pmwc.Register(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "CPeakMeterWndClass::Init failed, code: %i", hr); goto error_cleanup; } fWndClassRegistered = TRUE;
// create the wizard header fonts
hr = sinfo.CreateTitleFont(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "CreateTitleFont failed"); goto error_cleanup; } fTitleFontCreated = TRUE; hr = sinfo.CreateBoldFont(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "CreateBoldFont failed"); goto error_cleanup; } fBoldFontCreated = TRUE;
// prepare the wizard pages
PROPSHEETPAGE psp; HPROPSHEETPAGE rghpsp[10]; PROPSHEETHEADER psh;
// Welcome page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT; //|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = WelcomeProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOME);
rghpsp[0] = CreatePropertySheetPage(&psp); if (rghpsp[0] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Full Duplex Test Page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT;//|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = FullDuplexProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_FULLDUPLEXTEST);
rghpsp[1] = CreatePropertySheetPage(&psp); if (rghpsp[1] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Microphone Test Page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT; //|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = MicTestProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_MICTEST);
rghpsp[2] = CreatePropertySheetPage(&psp); if (rghpsp[2] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Microphone Failed Page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT;//|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = MicTestFailedProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_MICTEST_FAILED);
rghpsp[3] = CreatePropertySheetPage(&psp); if (rghpsp[3] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Speaker Test Page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT;//|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = SpeakerTestProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_SPEAKER_TEST);
rghpsp[4] = CreatePropertySheetPage(&psp); if (rghpsp[4] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Wizard Complete Page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT;//|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = CompleteProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPLETE);
rghpsp[5] = CreatePropertySheetPage(&psp); if (rghpsp[5] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// half duplex failed page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT;//|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = HalfDuplexFailedProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_HALFDUPLEXFAILED);
rghpsp[6] = CreatePropertySheetPage(&psp); if (rghpsp[6] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Full duplex failed page
ZeroMemory(&psp, sizeof(psp)); // psp.dwSize = sizeof(psp);
psp.dwSize = PROPSHEETPAGE_STRUCT_SIZE; psp.dwFlags = PSP_DEFAULT;//|PSP_HIDEHEADER;
psp.hInstance = g_hResDLLInstance; psp.lParam = (LPARAM) &sinfo; psp.pfnDlgProc = FullDuplexFailedProc; psp.pszTemplate = MAKEINTRESOURCE(IDD_FULLDUPLEXFAILED);
rghpsp[7] = CreatePropertySheetPage(&psp); if (rghpsp[7] == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreatePropertySheetPage failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Put it all together...
ZeroMemory(&psh, sizeof(psh)); // psh.dwSize = sizeof(psh);
psh.dwSize = PROPSHEETHEAD_STRUCT_SIZE; psh.hInstance = g_hResDLLInstance; psh.hwndParent = hwndParent; psh.phpage = rghpsp; psh.dwFlags = PSH_WIZARD; psh.nStartPage = 0; psh.nPages = 8;
sinfo.SetError(DV_OK); iRet = (INT) PropertySheet(&psh); if (iRet == -1) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "PropertySheet failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hr = sinfo.DestroyBoldFont(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DestroyBoldFont failed"); goto error_cleanup; } fBoldFontCreated = FALSE; hr = sinfo.DestroyTitleFont(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DestroyTitleFont failed"); goto error_cleanup; } fTitleFontCreated = FALSE;
// unregister the peak meter window class
hr = pmwc.Unregister(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "CPeakMeterWndClass::Deinit failed, code: %i", hr); goto error_cleanup; } fWndClassRegistered = FALSE;
if (!FreeLibrary(g_hResDLLInstance)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "FreeLibrary failed, code: %i", lRet); hr = DVERR_WIN32; goto error_cleanup; } g_hResDLLInstance = NULL;
// see if an error occured
sinfo.GetError(&hr); if (hr == DV_OK) { // nothing out of the ordinary happened,
// so we'll return a cancel if the user
// hit cancel, a "user back" if the user exited
// the wizard by hitting back from the welcome
// page, or the results from the registry otherwise.
sinfo.GetUserCancel(&fUserCancel); sinfo.GetUserBack(&fUserBack); if (fUserCancel & fUserBack) { hr = DVERR_USERBACK; } else if(fUserCancel) { hr = DVERR_USERCANCEL; } else { // look in the registry for the test results
hr = sinfo.QueryFullDuplex();
// map a run setup result to a total failure
if (hr == DVERR_RUNSETUP) { hr = DVERR_SOUNDINITFAILURE; } } }
// close the mutex
sinfo.CloseMutex(); // close the registry key
sinfo.CloseRegKey();
DPF_EXIT(); return hr; error_cleanup: if (fBoldFontCreated == TRUE) { sinfo.DestroyBoldFont(); } fBoldFontCreated = FALSE;
if (fTitleFontCreated == TRUE) { sinfo.DestroyTitleFont(); } fTitleFontCreated = FALSE;
if (fWndClassRegistered == TRUE) { pmwc.Unregister(); } fWndClassRegistered = FALSE;
if (g_hResDLLInstance != NULL) { FreeLibrary(g_hResDLLInstance); } g_hResDLLInstance = NULL;
if (fMutexOpen == TRUE) { sinfo.CloseMutex(); } fMutexOpen = FALSE;
if (fRegKeyOpen == TRUE) { sinfo.CloseRegKey(); } fRegKeyOpen = FALSE;
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "SupervisorQueryAudioSetup"
HRESULT SupervisorQueryAudioSetup(CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr;
// will return DV_HALFDUPLEX, DV_FULLDUPLEX, DVERR_SOUNDINITFAILURE or a real error
hr = psinfo->QueryFullDuplex(); if (FAILED(hr) && hr != DVERR_SOUNDINITFAILURE && hr != DVERR_RUNSETUP) { Diagnostics_Write(DVF_ERRORLEVEL, "QueryFullDuplex failed, code: %i", hr); } DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CreateTitleFont"
HRESULT CSupervisorInfo::CreateTitleFont() { DPF_ENTER(); LONG lRet; HRESULT hr; HFONT hfTitle = NULL; INT iFontSize; LOGFONT lfTitle; HDC hdc = NULL; NONCLIENTMETRICS ncm;
DNEnterCriticalSection(&m_csLock); // Set up the font for the titles on the intro and ending pages
ZeroMemory(&ncm, sizeof(ncm)); ncm.cbSize = sizeof(ncm); if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "SystemParametersInfo failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Create the intro/end title font
lfTitle = ncm.lfMessageFont; lfTitle.lfWeight = FW_BOLD; lstrcpy(lfTitle.lfFaceName, TEXT("MS Shell Dlg"));
hdc = GetDC(NULL); //gets the screen DC
if (hdc == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDC failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } iFontSize = 12; lfTitle.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * iFontSize / 72; hfTitle = CreateFontIndirect(&lfTitle); if (hfTitle == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreateFontIndirect failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } if (ReleaseDC(NULL, hdc) != 1) { hdc = NULL; lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "ReleaseDC failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// save the font
m_hfTitle = hfTitle;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup:
if (hfTitle != NULL) { DeleteObject(hfTitle); } hfTitle = NULL; if (hdc != NULL) { ReleaseDC(NULL, hdc); } hdc = NULL;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::DestroyTitleFont"
HRESULT CSupervisorInfo::DestroyTitleFont() { DPF_ENTER(); HFONT hTitleFont; LONG lRet; HRESULT hr;
DNEnterCriticalSection(&m_csLock);
if (m_hfTitle == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "m_hTitleFont is Null"); hr = DVERR_GENERIC; goto error_cleanup; }
if (!DeleteObject(m_hfTitle)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "DeleteObject failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CreateBoldFont"
HRESULT CSupervisorInfo::CreateBoldFont() { DPF_ENTER(); LONG lRet; HRESULT hr; HFONT hfBold = NULL; INT iFontSize; LOGFONT lfBold; HDC hdc = NULL; NONCLIENTMETRICS ncm;
DNEnterCriticalSection(&m_csLock); // Set up the font for the titles on the intro and ending pages
ZeroMemory(&ncm, sizeof(ncm)); ncm.cbSize = sizeof(ncm); if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "SystemParametersInfo failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Create the intro/end title font
lfBold = ncm.lfMessageFont; lfBold.lfWeight = FW_BOLD; lstrcpy(lfBold.lfFaceName, TEXT("MS Shell Dlg"));
hdc = GetDC(NULL); //gets the screen DC
if (hdc == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDC failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } iFontSize = 8; lfBold.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * iFontSize / 72; hfBold = CreateFontIndirect(&lfBold); if (hfBold == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "CreateFontIndirect failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } if (ReleaseDC(NULL, hdc) != 1) { hdc = NULL; lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "ReleaseDC failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// save the font
m_hfBold = hfBold;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: if (hdc != NULL) { ReleaseDC(NULL, hdc); } hdc = NULL;
if (hfBold != NULL) { DeleteObject(hfBold); } hfBold = NULL;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::DestroyBoldFont"
HRESULT CSupervisorInfo::DestroyBoldFont() { DPF_ENTER(); HFONT hTitleFont; LONG lRet; HRESULT hr;
DNEnterCriticalSection(&m_csLock);
if (m_hfBold == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "m_hTitleFont is Null"); hr = DVERR_GENERIC; goto error_cleanup; }
if (!DeleteObject(m_hfBold)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "DeleteObject failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } m_hfBold = NULL;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::Unmute"
HRESULT CSupervisorInfo::Unmute() { DPF_ENTER(); LONG lRet; HRESULT hr; DVCLIENTCONFIG dvcc;
DNEnterCriticalSection(&m_csLock);
if (m_lpdpvc == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "NULL IDirectPlayVoiceClient"); hr = DVERR_INVALIDPARAM; goto error_cleanup; }
dvcc.dwSize = sizeof(dvcc); hr = m_lpdpvc->GetClientConfig(&dvcc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "IDirectPlayVoiceClient::GetClientConfig failed, hr: %i", hr); goto error_cleanup; } dvcc.dwFlags &= (~DVCLIENTCONFIG_PLAYBACKMUTE); m_lpdpvc->SetClientConfig(&dvcc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "IDirectPlayVoiceClient::SetClientConfig failed, hr: %i", hr); goto error_cleanup; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::Mute"
HRESULT CSupervisorInfo::Mute() { DPF_ENTER(); LONG lRet; HRESULT hr; DVCLIENTCONFIG dvcc;
DNEnterCriticalSection(&m_csLock);
if (m_lpdpvc == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "NULL IDirectPlayVoiceClient"); hr = DVERR_INVALIDPARAM; goto error_cleanup; }
dvcc.dwSize = sizeof(dvcc); hr = m_lpdpvc->GetClientConfig(&dvcc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "IDirectPlayVoiceClient::GetClientConfig failed, hr: %i", hr); goto error_cleanup; } dvcc.dwFlags |= DVCLIENTCONFIG_PLAYBACKMUTE; m_lpdpvc->SetClientConfig(&dvcc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "IDirectPlayVoiceClient::SetClientConfig failed, hr: %i", hr); goto error_cleanup; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::DSEnumCallback"
BOOL CALLBACK CSupervisorInfo::DSEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext) { DNASSERT(lpContext); CSupervisorInfo* psinfo = (CSupervisorInfo*)lpContext;
if (lpGuid) { if (psinfo->m_guidRenderDevice == *lpGuid) { // matching guid, copy the description
_tcsncpy(psinfo->m_szRenderDeviceDesc, lpcstrDescription, MAX_DEVICE_DESC_LEN-1);
// all done, stop enum
return FALSE; } } return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::DSCEnumCallback"
BOOL CALLBACK CSupervisorInfo::DSCEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext) { DNASSERT(lpContext); CSupervisorInfo* psinfo = (CSupervisorInfo*)lpContext;
if (lpGuid) { if (psinfo->m_guidCaptureDevice == *lpGuid) { // matching guid, copy the description
_tcsncpy(psinfo->m_szCaptureDeviceDesc, lpcstrDescription, MAX_DEVICE_DESC_LEN-1);
// all done, stop enum
return FALSE; } } return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::GetDeviceDescriptions"
HRESULT CSupervisorInfo::GetDeviceDescriptions() { DPF_ENTER();
HRESULT hr; TDirectSoundEnumFnc fpDSEnum; TDirectSoundEnumFnc fpDSCEnum; DNEnterCriticalSection(&m_csLock);
ZeroMemory(m_szRenderDeviceDesc, MAX_DEVICE_DESC_LEN); ZeroMemory(m_szCaptureDeviceDesc, MAX_DEVICE_DESC_LEN);
HINSTANCE hDSound = LoadLibrary(_T("dsound.dll")); if (hDSound == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "Error loading dsound.dll"); hr = DVERR_SOUNDINITFAILURE; goto error_cleanup; }
#ifdef UNICODE
fpDSEnum = (TDirectSoundEnumFnc)GetProcAddress(hDSound, "DirectSoundEnumerateW"); #else
fpDSEnum = (TDirectSoundEnumFnc)GetProcAddress(hDSound, "DirectSoundEnumerateA"); #endif
if (fpDSEnum == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "GetProcAddress failed for DirectSoundEnumerateW"); hr = DVERR_SOUNDINITFAILURE; goto error_cleanup; }
#ifdef UNICODE
fpDSCEnum = (TDirectSoundEnumFnc)GetProcAddress(hDSound, "DirectSoundCaptureEnumerateW"); #else
fpDSCEnum = (TDirectSoundEnumFnc)GetProcAddress(hDSound, "DirectSoundCaptureEnumerateA"); #endif
if (fpDSCEnum == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "GetProcAddress failed for DirectSoundCaptureEnumerateW"); hr = DVERR_SOUNDINITFAILURE; goto error_cleanup; }
hr = fpDSEnum(DSEnumCallback, (LPVOID)this); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DirectSoundEnumerate failed, code: %i, assuming bad guid", hr); hr = DVERR_INVALIDDEVICE; goto error_cleanup; } if (m_szRenderDeviceDesc[0] == NULL) { // the device wasn't found!
Diagnostics_Write(DVF_ERRORLEVEL, "Render device not found"); hr = DVERR_INVALIDDEVICE; goto error_cleanup; }
hr = fpDSCEnum(DSCEnumCallback, (LPVOID)this); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DirectSoundCaptureEnumerate failed, code: %i, assuming bad guid", hr); hr = DVERR_INVALIDDEVICE; goto error_cleanup; } if (m_szCaptureDeviceDesc[0] == NULL) { // the device wasn't found!
Diagnostics_Write(DVF_ERRORLEVEL, "Capture device not found"); hr = DVERR_INVALIDDEVICE; goto error_cleanup; }
FreeLibrary( hDSound ); DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK;
error_cleanup:
if( hDSound != NULL ) { FreeLibrary( hDSound ); } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CloseRegKey"
HRESULT CSupervisorInfo::CloseRegKey() { DPF_ENTER(); LONG lRet; HRESULT hr; DNEnterCriticalSection(&m_csLock);
if (!m_creg.Close()) { Diagnostics_Write(DVF_ERRORLEVEL, "CRegistry::Close failed"); hr = DVERR_GENERIC; goto error_cleanup; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK;
error_cleanup: DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexTestThreadProc"
DWORD WINAPI FullDuplexTestThreadProc(LPVOID lpvParam) { DPF_ENTER(); CSupervisorInfo* lpsinfo; CSupervisorIPC* lpipcSupervisor; LPGUID lpguidRenderDevice; LPGUID lpguidCaptureDevice; HKEY hkDevice; HRESULT hr; LONG lRet; HWND hwnd;
lpsinfo = (CSupervisorInfo*)lpvParam;
lpsinfo->GetHWNDDialog(&hwnd);
hr = RunFullDuplexTest(lpsinfo);
// post a message to the wizard so it knows we're done, but
// only if this was not a user cancel, since the wizard will
// already be waiting on the thread object
if (hr != DVERR_USERCANCEL) { if (!PostMessage(hwnd, WM_APP_FULLDUP_TEST_COMPLETE, 0, (LPARAM)hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "PostMessage failed, code: %i", lRet); hr = DVERR_GENERIC; } }
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "RunFullDuplexTest"
static HRESULT RunFullDuplexTest(CSupervisorInfo* lpsinfo) { DPF_ENTER(); HRESULT hr; HRESULT hrFnc; CSupervisorIPC* lpsipc; lpsinfo->GetIPC(&lpsipc);
hr = lpsipc->StartPriorityProcess(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "StartPriorityProcess failed, hr: %i", hr); goto error_cleanup; } hr = lpsipc->StartFullDuplexProcess(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "StartFullDuplexProcess failed, hr: %i", hr); goto error_cleanup; }
hrFnc = DoTests(lpsinfo);
hr = lpsipc->WaitOnChildren(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "WaitOnChildren failed, code: %i", hr); goto error_cleanup; } DPF_EXIT(); return hrFnc;
error_cleanup: // this function is safe to call, even if the child processes have not
// been created
lpsipc->TerminateChildProcesses(); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::CrashCheckIn"
HRESULT CSupervisorInfo::CrashCheckIn() { DPF_ENTER();
LONG lRet; BOOL fRet; DWORD dwRegVal; HRESULT hrFnc; HRESULT hr; HKEY hk;
// Each of the following three functions take the critical section,
// so there is no need to take it here.
// Check each of the test results to see if any tests
// crashed.
hr = GetHalfDuplex(&dwRegVal); if (!FAILED(hr) && dwRegVal == REGVAL_CRASHED) { // The half duplex test crashed.
Diagnostics_Write(DVF_ERRORLEVEL, "Previous half duplex test crashed"); hrFnc = DVERR_PREVIOUSCRASH; goto error_cleanup; }
hr = GetFullDuplex(&dwRegVal); if (!FAILED(hr) && dwRegVal == REGVAL_CRASHED) { // The full duplex test crashed.
Diagnostics_Write(DVF_ERRORLEVEL, "Previous full duplex test crashed"); hrFnc = DVERR_PREVIOUSCRASH; goto error_cleanup; }
hr = GetMicDetected(&dwRegVal); if (!FAILED(hr) && dwRegVal == REGVAL_CRASHED) { // The mic test crashed.
Diagnostics_Write(DVF_ERRORLEVEL, "Previous mic test crashed"); hrFnc = DVERR_PREVIOUSCRASH; goto error_cleanup; }
DPF_EXIT(); return DV_OK;
// error block
error_cleanup: DPF_EXIT(); return hrFnc; }
#undef DPF_MODNAME
#define DPF_MODNAME "DoTests"
HRESULT DoTests(CSupervisorInfo* lpsinfo) {
DPF_ENTER(); LONG lRet; DWORD dwRet; HANDLE rghEvents[2]; HRESULT hr; HRESULT hrFnc; CSupervisorIPC* lpsipc;
lpsinfo->GetIPC(&lpsipc);
// wait until the child processes are ready to go...
hr = lpsipc->WaitForStartupSignals(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "WaitForStartupSignals failed, hr: %i", hr); goto error_cleanup; }
// child processes are all set, tell them what to do
// Note: this function has only four expected return codes
// DV_FULLDUPLEX - all tests passed
// DV_HALFDUPLEX - all half duplex tests passed, full duplex tests failed
// DVERR_SOUNDINITFAILURE - half duplex tests failed
// DVERR_USERCANCEL - tests canceled by user
hrFnc = IssueCommands(lpsinfo); if (FAILED(hrFnc) && hrFnc != DVERR_SOUNDINITFAILURE && hrFnc != DVERR_USERCANCEL) { Diagnostics_Write(DVF_ERRORLEVEL, "IssueCommands failed, hr: %i", hrFnc); hr = hrFnc; goto error_cleanup; }
// now tell the child processes to shut down
hr = IssueShutdownCommand(lpsipc); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "IssueShutdownCommand failed, code: %i", hr); // Note we're not bailing out. We have our test results, so this is
// a problem somewhere in the wizard code. Return the result
// from the actual test.
} DPF_EXIT(); return hrFnc;
error_cleanup: // attempt to gracefully shutdown child processes.
IssueShutdownCommand(lpsipc); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "IssueCommands"
HRESULT IssueCommands(CSupervisorInfo* lpsinfo) { // Note: this function has only four possible return codes
// DV_FULLDUPLEX - all tests passed
// DV_HALFDUPLEX - all half duplex tests passed, full duplex tests failed
// DVERR_SOUNDINITFAILURE - half duplex tests failed
// DVERR_USERCANCEL - tests canceled by user
DPF_ENTER(); HRESULT hr; DWORD dwIndex1; DWORD dwIndex2; BOOL fAbort = FALSE; BOOL fPassed;
// First do a pass testing that we can run in
// half duplex without error.
// Set the half duplex key to crash state
lpsinfo->SetHalfDuplex(REGVAL_CRASHED); dwIndex1 = 0; fPassed = FALSE; while (1) { if (gc_rgwfxPrimaryFormats[dwIndex1].wFormatTag == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nChannels == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nSamplesPerSec == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nAvgBytesPerSec == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nBlockAlign == 0 && gc_rgwfxPrimaryFormats[dwIndex1].wBitsPerSample == 0 && gc_rgwfxPrimaryFormats[dwIndex1].cbSize == 0) { // we've found the last element of the array, break out.
fPassed = TRUE; break; }
lpsinfo->GetAbortFullDuplex(&fAbort); if (fAbort) { // abort the tests
break; }
hr = lpsinfo->TestCase(&gc_rgwfxPrimaryFormats[dwIndex1], DVSOUNDCONFIG_HALFDUPLEX|DVSOUNDCONFIG_TESTMODE); if (hr != DV_HALFDUPLEX) { Diagnostics_Write(DVF_ERRORLEVEL, "Half duplex test case not supported hr = 0x%x", hr); break; } ++dwIndex1;
// Why is this here? Because DSOUND doesn't like you to open/close quickly.
Sleep( 200 ); }
if (fAbort) { // The user aborted the tests, make it like they were never run.
lpsinfo->SetHalfDuplex(REGVAL_NOTRUN); DPF_EXIT(); return DVERR_USERCANCEL; }
// Record the results of the half duplex test in the registry,
// and decide what to do next.
if (fPassed) { lpsinfo->SetHalfDuplex(REGVAL_PASSED); // continue on with the full duplex test.
} else { lpsinfo->SetHalfDuplex(REGVAL_FAILED); // we failed the half duplex test, we're done.
DPF_EXIT(); // map all failures at this point to sound problems.
return DVERR_SOUNDINITFAILURE; }
// Now that we're finished testing in half duplex mode,
// we can move on to the full duplex testing.
lpsinfo->SetFullDuplex(REGVAL_CRASHED); fPassed = FALSE; dwIndex1 = 0; while (1) { if (gc_rgwfxPrimaryFormats[dwIndex1].wFormatTag == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nChannels == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nSamplesPerSec == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nAvgBytesPerSec == 0 && gc_rgwfxPrimaryFormats[dwIndex1].nBlockAlign == 0 && gc_rgwfxPrimaryFormats[dwIndex1].wBitsPerSample == 0 && gc_rgwfxPrimaryFormats[dwIndex1].cbSize == 0) { // we've found the last element of the array, break out.
fPassed = TRUE; break; }
lpsinfo->GetAbortFullDuplex(&fAbort); if (fAbort) { // abort the tests
break; }
hr = lpsinfo->TestCase(&gc_rgwfxPrimaryFormats[dwIndex1], DVSOUNDCONFIG_TESTMODE); if (hr != DV_FULLDUPLEX) { Diagnostics_Write(DVF_ERRORLEVEL, "Full duplex test case not supported. hr = 0x%x", hr); break; } ++dwIndex1;
// Why is this here? Because DSOUND doesn't like you to open/close quickly.
Sleep( 200 ); }
if (fAbort) { // The user aborted the tests, make it like they were never run.
lpsinfo->SetFullDuplex(REGVAL_NOTRUN); DPF_EXIT(); return DVERR_USERCANCEL; }
// Record the results of the full duplex test in the registry,
// and return the appropriate code.
if (fPassed) { lpsinfo->SetFullDuplex(REGVAL_PASSED); DPF_EXIT(); return DV_FULLDUPLEX; } else { lpsinfo->SetFullDuplex(REGVAL_FAILED); DPF_EXIT(); return DV_HALFDUPLEX; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorInfo::TestCase"
HRESULT CSupervisorInfo::TestCase(const WAVEFORMATEX* lpwfxPrimary, DWORD dwFlags) { DPF_ENTER(); HRESULT hr = DV_OK; HRESULT hrFnc = DV_OK; SFDTestCommand fdtc;
// tell the priority process to go
ZeroMemory(&fdtc, sizeof(fdtc)); fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccPriorityStart; fdtc.fdtu.fdtcPriorityStart.guidRenderDevice = m_guidRenderDevice; fdtc.fdtu.fdtcPriorityStart.wfxRenderFormat = *lpwfxPrimary; fdtc.fdtu.fdtcPriorityStart.wfxSecondaryFormat = gc_wfxSecondaryFormat; fdtc.fdtu.fdtcPriorityStart.hwndWizard = m_hwndWizard; fdtc.fdtu.fdtcPriorityStart.hwndProgress = m_hwndProgress; hr = m_sipc.SendToPriority(&fdtc); if (FAILED(hr)) { DPF_EXIT(); return hr; }
// tell the full duplex process to attempt full duplex
ZeroMemory(&fdtc, sizeof(fdtc)); fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccFullDuplexStart; fdtc.fdtu.fdtcFullDuplexStart.guidRenderDevice = m_guidRenderDevice; fdtc.fdtu.fdtcFullDuplexStart.guidCaptureDevice = m_guidCaptureDevice; fdtc.fdtu.fdtcFullDuplexStart.dwFlags = dwFlags; hrFnc = m_sipc.SendToFullDuplex(&fdtc); if (FAILED(hrFnc)) { // The full duplex process was unable to do it.
// tell the priority process to stop and get out.
ZeroMemory(&fdtc, sizeof(fdtc)); fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccPriorityStop; m_sipc.SendToPriority(&fdtc); DPF_EXIT(); return hrFnc; }
// Wait for a half second before we shut it down.
// This gives it the time required for the sound system
// to detect a lockup if it is going to.
Sleep(1000); // The full duplex process was ok, till now. Try to
// shut it down.
ZeroMemory(&fdtc, sizeof(fdtc)); fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccFullDuplexStop; hr = m_sipc.SendToFullDuplex(&fdtc); if (FAILED(hr)) { // It looks like the full duplex wasn't quite up to stuff
// after all. Tell the priority process to shut down
ZeroMemory(&fdtc, sizeof(fdtc)); fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccPriorityStop; m_sipc.SendToPriority(&fdtc); DPF_EXIT(); return hr; }
// All is well, up to now, one last hurdle...
ZeroMemory(&fdtc, sizeof(fdtc)); fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccPriorityStop; hr = m_sipc.SendToPriority(&fdtc); if (FAILED(hr)) { DPF_EXIT(); return hr; }
// you have graduated from full duplex class...
DPF_EXIT(); return hrFnc; }
#undef DPF_MODNAME
#define DPF_MODNAME "IssueShutdownCommand"
HRESULT IssueShutdownCommand(CSupervisorIPC* lpipcSupervisor) { SFDTestCommand fdtc; HRESULT hr;
DPF_EXIT();
fdtc.dwSize = sizeof(fdtc); fdtc.fdtcc = fdtccExit;
hr = lpipcSupervisor->SendToFullDuplex(&fdtc); if (FAILED(hr)) { lpipcSupervisor->SendToPriority(&fdtc); DPF_EXIT(); return hr; }
hr = lpipcSupervisor->SendToPriority(&fdtc); if (FAILED(hr)) { DPF_EXIT(); return hr; }
DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "WelcomeProc"
INT_PTR CALLBACK WelcomeProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); BOOL fRet;
CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : fRet = WelcomeInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : { LPNMHDR lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : // Enable the Next button
fRet = WelcomeSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : // Back button clicked
fRet = WelcomeBackHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZNEXT : // Next button clicked
fRet = WelcomeNextHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = WelcomeResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } } break;
default: break; } DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "WelcomeInitDialogHandler"
BOOL WelcomeInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HWND hwndControl; HWND hwndWizard = NULL; LONG lRet; HFONT hfTitle; HICON hIcon; HRESULT hr = DV_OK; HWND hwndParent = NULL; // Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo);
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// It's an intro/end page, so get the title font
// from the shared data and use it for the title control
hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetTitleFont(&hfTitle); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfTitle, (LPARAM)TRUE); // load the warning icon
//hIcon = LoadIcon(NULL, IDI_INFORMATION);
//SendDlgItemMessage(hDlg, IDC_WARNINGICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
// set the device descriptions
SendDlgItemMessage(hDlg, IDC_TEXT_PLAYBACK, WM_SETTEXT, 0, (LPARAM)psinfo->GetRenderDesc()); SendDlgItemMessage(hDlg, IDC_TEXT_RECORDING, WM_SETTEXT, 0, (LPARAM)psinfo->GetCaptureDesc());
// reset the welcome next flag
psinfo->ClearWelcomeNext();
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "WelcomeSetActiveHandler"
BOOL WelcomeSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HWND hwndParent; HWND hwndWizard; LONG lRet; DWORD dwFlags; HRESULT hr;
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { // log it, and return, don't know how to terminate the wizard properly
// without this handle!
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(NULL); psinfo->SetHWNDOutputPeak(NULL); psinfo->SetHWNDInputVolumeSlider(NULL); psinfo->SetHWNDOutputVolumeSlider(NULL);
// set the appropriate wizard buttons as active.
psinfo->GetCheckAudioSetupFlags(&dwFlags); if (dwFlags & DVFLAGS_ALLOWBACK) { PropSheet_SetWizButtons(hwndWizard, PSWIZB_NEXT|PSWIZB_BACK); } else { PropSheet_SetWizButtons(hwndWizard, PSWIZB_NEXT); }
// reset the user cancel and user back flags
psinfo->ClearUserCancel(); psinfo->ClearUserBack();
DPF_EXIT(); return FALSE;
// error block
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "WelcomeBackHandler"
BOOL WelcomeBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HWND hwndWizard = NULL; HRESULT hr = DV_OK; LPGUID lpguidCaptureDevice; LPGUID lpguidRenderDevice; HKEY hkey; LONG lRet; DWORD dwErr; DWORD dwRegVal;
// Get the parent window
psinfo->GetHWNDWizard(&hwndWizard); // The back button was hit on the welcome page. Exit the wizard with the appropriate error code.
psinfo->SetUserBack(); PropSheet_PressButton(hwndWizard, PSBTN_CANCEL);
// no previous crashes (or the user is boldly charging ahead anyway),
// so go to the full duplex test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXTEST); DPF_EXIT(); return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "WelcomeNextHandler"
BOOL WelcomeNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HWND hwndWizard = NULL; HRESULT hr = DV_OK; LPGUID lpguidCaptureDevice; LPGUID lpguidRenderDevice; HKEY hkey; LONG lRet; DWORD dwErr; DWORD dwRegVal; HWND hwndParent = NULL;
// Get the parent window
psinfo->GetHWNDWizard(&hwndWizard); // The next button was hit on the welcome page. Do all the basic init tasks.
// check for previous crashes
hr = psinfo->CrashCheckIn(); if (FAILED(hr)) { if (hr == DVERR_PREVIOUSCRASH) { // the previous test crashed out, display the warning.
Diagnostics_Write(DVF_ERRORLEVEL, "DirectPlay Voice Setup Wizard detected previous full duplex test crashed"); int iRet = (INT) DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_PREVIOUS_CRASH), hDlg, PreviousCrashProc); switch (iRet) { case IDOK: // the previous test crashed, but the user wants to continue
// anyway, so move along...
Diagnostics_Write(DVF_ERRORLEVEL, "User choosing to ignore previous failure"); break; case IDCANCEL: // the previous test crashed, and the user is wisely choosing
// to bail out. Go to either the full duplex failed page, or the
// half duplex failed page, depending on the registry state.
Diagnostics_Write(DVF_ERRORLEVEL, "User choosing not to run test"); hr = psinfo->GetHalfDuplex(&dwRegVal); if (!FAILED(hr) && dwRegVal == REGVAL_PASSED) { SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXFAILED); } else { SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_HALFDUPLEXFAILED); } return TRUE; break; default: // this is an error
Diagnostics_Write(DVF_ERRORLEVEL, "DialogBox failed"); hr = DVERR_GENERIC; goto error_cleanup; } } else { Diagnostics_Write(DVF_ERRORLEVEL, "CrashCheckIn failed, code: %i", hr); goto error_cleanup; } }
// no previous crashes (or the user is boldly charging ahead anyway),
// so go to the full duplex test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXTEST); DPF_EXIT(); return TRUE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "WelcomeResetHandler"
BOOL WelcomeResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr; HWND hwndWizard;
// disable all buttons
psinfo->GetHWNDWizard(&hwndWizard); PropSheet_SetWizButtons(hwndWizard, 0);
psinfo->Cancel(); DPF_EXIT(); return FALSE; }
/*
#undef DPF_MODNAME
#define DPF_MODNAME "AlreadyRunningProc"
INT_PTR CALLBACK AlreadyRunningProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); HICON hIcon;
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)); return TRUE;
default: break; } break;
default: break; } DPF_EXIT(); return FALSE; } */
#undef DPF_MODNAME
#define DPF_MODNAME "PreviousCrashProc"
INT_PTR CALLBACK PreviousCrashProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); LPNMHDR lpnm; HICON hIcon;
Diagnostics_Write(DVF_ERRORLEVEL, "Previous run crashed");
switch (message) { case WM_INITDIALOG : PlaySound( _T("SystemExclamation"), NULL, SND_ASYNC ); 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)); return(TRUE); break;
default: break; } break; default: break; } DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexProc"
INT_PTR CALLBACK FullDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); LONG lRet; BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : FullDuplexInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = FullDuplexSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : fRet = FullDuplexBackHandler(hDlg, message, wParam, lParam, psinfo); break; case PSN_WIZNEXT : fRet = FullDuplexNextHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = FullDuplexResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } break;
case WM_APP_FULLDUP_TEST_COMPLETE: fRet = FullDuplexCompleteHandler(hDlg, message, wParam, lParam, psinfo); break;
default: break; } DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexInitDialogHandler"
BOOL FullDuplexInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfBold; HRESULT hr = DV_OK; // Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetBoldFont(&hfBold); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfBold, (LPARAM)TRUE);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexSetActiveHandler"
BOOL FullDuplexSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndProgress; HWND hwndCancelButton; HANDLE hThread; DWORD dwThreadId; WORD wCount; HRESULT hr = DV_OK;
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// reset all the test registry bits
psinfo->SetHalfDuplex(REGVAL_NOTRUN); psinfo->SetFullDuplex(REGVAL_NOTRUN); psinfo->SetMicDetected(REGVAL_NOTRUN);
// remember that we've been here, so we'll know to reset the registry
// if the user hits cancel from this point forward
psinfo->SetWelcomeNext();
// get the progress bar's HWND
hwndProgress = GetDlgItem(hDlg, IDC_PROGRESSBAR); if (hwndProgress == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Init the progress bar...
// count the number of elements in the primary format array
wCount = 0; while (1) { // Increment before we test. This means that if there
// are four formats, wCount will equal five after this
// loop.
++wCount; if (gc_rgwfxPrimaryFormats[wCount].wFormatTag == 0 && gc_rgwfxPrimaryFormats[wCount].nChannels == 0 && gc_rgwfxPrimaryFormats[wCount].nSamplesPerSec == 0 && gc_rgwfxPrimaryFormats[wCount].nAvgBytesPerSec == 0 && gc_rgwfxPrimaryFormats[wCount].nBlockAlign == 0 && gc_rgwfxPrimaryFormats[wCount].wBitsPerSample == 0 && gc_rgwfxPrimaryFormats[wCount].cbSize == 0) { // we've found the last element of the array, break out.
break; } }
// set up the progress bar with one segment for each
// primary format, times two, since each is tested in
// both half and full duplex.
SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, wCount*2)); SendMessage(hwndProgress, PBM_SETPOS, 0, 0); SendMessage(hwndProgress, PBM_SETSTEP, 1, 0);
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(hwndProgress); psinfo->SetHWNDInputPeak(NULL); psinfo->SetHWNDOutputPeak(NULL); psinfo->SetHWNDInputVolumeSlider(NULL); psinfo->SetHWNDOutputVolumeSlider(NULL);
// clear the abort flag!
psinfo->ClearAbortFullDuplex();
// enable the Back button only
PropSheet_SetWizButtons(hwndWizard, PSWIZB_BACK);
// init IPC stuff
hr = psinfo->InitIPC(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "Unable to Initialize IPC"); goto error_cleanup; }
// Fire up the full duplex test thread
hr = psinfo->CreateFullDuplexThread(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "CreateFullDuplexThread failed, code: %i", hr); goto error_cleanup; }
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexNextHandler"
BOOL FullDuplexNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); BOOL fPassed; HRESULT hr; HWND hwndWizard; HWND hwndParent = NULL;
psinfo->GetFullDuplexResults(&hr);
switch (hr) { case DV_HALFDUPLEX: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXFAILED); Diagnostics_Write(DVF_ERRORLEVEL, "Test resulted in full duplex"); break; case DV_FULLDUPLEX: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_MICTEST); Diagnostics_Write(DVF_ERRORLEVEL, "Test resulted in full duplex"); break;
case DVERR_SOUNDINITFAILURE: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_HALFDUPLEXFAILED); Diagnostics_Write(DVF_ERRORLEVEL, "Test encountered unrecoverable error"); break;
default: // we should not get any other result
Diagnostics_Write(DVF_ERRORLEVEL, "Unexpected full duplex results, hr: %i", hr); goto error_cleanup; }
DPF_EXIT(); return TRUE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexBackHandler"
BOOL FullDuplexBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr; HWND hwndWizard; HWND hwndParent = NULL;
// Get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
// shut down the full duplex test
hr = psinfo->CancelFullDuplexTest(); if (FAILED(hr) && hr != DVERR_USERCANCEL) { Diagnostics_Write(DVF_ERRORLEVEL, "CancelFullDuplexTest failed, hr: %i", hr); goto error_cleanup; }
// reset the registry to the "test not run" state
hr = psinfo->SetHalfDuplex(REGVAL_NOTRUN); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetHalfDuplex failed, code: %i", hr); }
hr = psinfo->SetFullDuplex(REGVAL_NOTRUN); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetFullDuplex failed, code: %i", hr); }
hr = psinfo->SetMicDetected(REGVAL_NOTRUN); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetMicDetected failed, code: %i", hr); }
// go back to the welcome page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_WELCOME);
DPF_EXIT(); return TRUE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexCompleteHandler"
BOOL FullDuplexCompleteHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndProgress; LONG lRet; HRESULT hr = DV_OK; UINT idsErrorMessage = 0;
// Get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
// Disable all the wizard buttons
PropSheet_SetWizButtons(hwndWizard, 0);
// Get the progress bar window
psinfo->GetHWNDProgress(&hwndProgress);
// Close the full duplex thread handle and get the test results via the exit code
hr = psinfo->WaitForFullDuplexThreadExitCode(); switch(hr) { case DVERR_SOUNDINITFAILURE: case DV_HALFDUPLEX: case DV_FULLDUPLEX: // These are the expected results from the full duplex test thread
// this means no strange internal error occured, and it is safe
// to move along to the next part of the wizard.
// Record the test results
psinfo->SetFullDuplexResults(hr); break;
case DPNERR_INVALIDDEVICEADDRESS: // This can result from no tcp/ip stack on the machine
// we want to dispaly a special error code and then fall
// through with the rest of the return codes.
idsErrorMessage = IDS_ERROR_NODEVICES; // fall through
default: // any other error code is not expected and means we hit
// some internal problem. Bail.
Diagnostics_Write(DVF_ERRORLEVEL, "Full duplex test thread exited with unexpected error code, hr: %i", hr); psinfo->DeinitIPC(); goto error_cleanup; }
// Deinit the IPC stuff
hr = psinfo->DeinitIPC(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DeinitIPC failed, code: %i", hr); goto error_cleanup; }
// Move the progress bar all the way to the end.
SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 1)); SendMessage(hwndProgress, PBM_SETPOS, 1, 0);
// enable and press the next button to move
// to the next page automatically
PropSheet_PressButton(hwndWizard, PSBTN_NEXT); DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent, idsErrorMessage); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexResetHandler"
BOOL FullDuplexResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestProc"
INT_PTR CALLBACK MicTestProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : fRet = MicTestInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = MicTestSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZNEXT : fRet = MicTestNextHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : fRet = MicTestBackHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = MicTestResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_RECADVANCED: fRet = MicTestRecAdvancedHandler(hDlg, message, wParam, lParam, psinfo); break;
default: break; } break;
case WM_APP_LOOPBACK_RUNNING: fRet = MicTestLoopbackRunningHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_APP_RECORDSTART: fRet = MicTestRecordStartHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_APP_RECORDSTOP: fRet = MicTestRecordStopHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_VSCROLL: fRet = MicTestVScrollHandler(hDlg, message, wParam, lParam, psinfo); break;
default: break; }
DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestInitDialogHandler"
BOOL MicTestInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfBold; HWND hwndRecPeak; HWND hwndOutPeak; HWND hwndRecSlider; HWND hwndOutSlider; HWND hwndOutAdvanced; HWND hwndOutGroup; HRESULT hr = DV_OK; // Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetBoldFont(&hfBold); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfBold, (LPARAM)TRUE);
// Get the peak meter
hwndRecPeak = GetDlgItem(hDlg, IDC_RECPEAKMETER); if (hwndRecPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Init the recording peak meter
SendMessage(hwndRecPeak, PM_SETMIN, 0, 0); SendMessage(hwndRecPeak, PM_SETMAX, 0, 99); SendMessage(hwndRecPeak, PM_SETCUR, 0, 0);
// Get the recording volume slider
hwndRecSlider = GetDlgItem(hDlg, IDC_RECVOL_SLIDER); if (hwndRecSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Init the recording volume slider
SendMessage(hwndRecSlider, TBM_SETRANGEMIN, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndRecSlider, TBM_SETRANGEMAX, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN)); SendMessage(hwndRecSlider, TBM_SETPOS, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndRecSlider, TBM_SETTICFREQ, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/10, 0); SendMessage(hwndRecSlider, TBM_SETLINESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/20); SendMessage(hwndRecSlider, TBM_SETPAGESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/5);
// Get the playback peak meter
hwndOutPeak = GetDlgItem(hDlg, IDC_OUTPEAKMETER); if (hwndOutPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Init the playback peak meter
SendMessage(hwndOutPeak, PM_SETMIN, 0, 0); SendMessage(hwndOutPeak, PM_SETMAX, 0, 99); SendMessage(hwndOutPeak, PM_SETCUR, 0, 0);
// Get the playback volume slider
hwndOutSlider = GetDlgItem(hDlg, IDC_OUTVOL_SLIDER); if (hwndOutSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Init the playback volume slider
SendMessage(hwndOutSlider, TBM_SETRANGEMIN, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndOutSlider, TBM_SETRANGEMAX, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN)); SendMessage(hwndOutSlider, TBM_SETPOS, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndOutSlider, TBM_SETTICFREQ, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/10, 0); SendMessage(hwndOutSlider, TBM_SETLINESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/20); SendMessage(hwndOutSlider, TBM_SETPAGESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/5);
// grey out all the playback volume stuff
EnableWindow(hwndOutSlider, FALSE); hwndOutAdvanced = GetDlgItem(hDlg, IDC_OUTADVANCED); if (hwndOutAdvanced == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } EnableWindow(hwndOutAdvanced, FALSE); hwndOutGroup = GetDlgItem(hDlg, IDC_OUTGROUP); if (hwndOutGroup == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } EnableWindow(hwndOutGroup, FALSE);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestSetActiveHandler"
BOOL MicTestSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndRecPeak; HWND hwndOutPeak; HWND hwndRecSlider; HWND hwndOutSlider; HANDLE hThread; HANDLE hEvent; DWORD dwThreadId; HRESULT hr = DV_OK; DWORD dwVolume;
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Set the recording peak meter to zero
hwndRecPeak = GetDlgItem(hDlg, IDC_RECPEAKMETER); if (hwndRecPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndRecPeak, PM_SETCUR, 0, 0);
// Get the recording volume control hwnd
hwndRecSlider = GetDlgItem(hDlg, IDC_RECVOL_SLIDER); if (hwndRecSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } // Set the slider to max
SendMessage(hwndRecSlider, TBM_SETPOS, 1, SendMessage(hwndRecSlider, TBM_GETRANGEMIN, 0, 0));
// Set the playback peak meter to zero
hwndOutPeak = GetDlgItem(hDlg, IDC_OUTPEAKMETER); if (hwndOutPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndOutPeak, PM_SETCUR, 0, 0);
// Get the playback volume control hwnd
hwndOutSlider = GetDlgItem(hDlg, IDC_OUTVOL_SLIDER); if (hwndOutSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Get the current waveOut volume and set the slider to that position
hr = psinfo->GetWaveOutVolume(&dwVolume); if (FAILED(hr)) { // couldn't get the volume - set the slider to top
SendMessage(hwndOutSlider, TBM_SETPOS, 1, SendMessage(hwndOutSlider, TBM_GETRANGEMIN, 0, 0)); } else { SendMessage(hwndOutSlider, TBM_SETPOS, 1, SendMessage(hwndOutSlider, TBM_GETRANGEMAX, 0, 0) - dwVolume); } // set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(hwndRecPeak); psinfo->SetHWNDOutputPeak(hwndOutPeak); psinfo->SetHWNDInputVolumeSlider(hwndRecSlider); psinfo->SetHWNDOutputVolumeSlider(NULL); psinfo->SetLoopbackFlags(0);
// clear the voice detected flag
psinfo->ClearVoiceDetected();
// clear the mic test reg value
psinfo->SetMicDetected(REGVAL_CRASHED);
// fire up the loopback test thread
hr = psinfo->CreateLoopbackThread(); if (FAILED(hr)) { // error, log it and bail
Diagnostics_Write(DVF_ERRORLEVEL, "CreateLoopbackThread failed, code: %i", hr); goto error_cleanup; } // disable the buttons - they will be enabled
// when the loopback test is up and running.
PropSheet_SetWizButtons(hwndWizard, 0);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestLoopbackRunningHandler"
BOOL MicTestLoopbackRunningHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HRESULT hr = DV_OK; HWND hwndRecordSlider; HWND hwndRecordAdvanced;
// Get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
// lParam is an HRESULT sent by the loopback test thread
hr = (HRESULT)lParam; if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "LoopbackTestThread signaled error, code: %i", hr); goto error_cleanup; }
hwndRecordSlider = GetDlgItem(hDlg, IDC_RECVOL_SLIDER); hwndRecordAdvanced = GetDlgItem( hDlg, IDC_RECADVANCED );
if( hwndRecordSlider != NULL && hwndRecordAdvanced != NULL ) { DWORD dwDeviceFlags;
psinfo->GetDeviceFlags( &dwDeviceFlags ); if( dwDeviceFlags & DVSOUNDCONFIG_NORECVOLAVAILABLE ) { EnableWindow( hwndRecordAdvanced, FALSE ); EnableWindow( hwndRecordSlider, FALSE ); } } else { hr = DVERR_GENERIC; DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get record slider window" ); goto error_cleanup; }
// clear the voice detected flag
psinfo->ClearVoiceDetected();
// enable the next button
PropSheet_SetWizButtons(hwndWizard, PSWIZB_NEXT|PSWIZB_BACK);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestRecordStartHandler"
BOOL MicTestRecordStartHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
// set the voice detected flag
psinfo->SetVoiceDetected();
DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestRecordStopHandler"
BOOL MicTestRecordStopHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestNextHandler"
BOOL MicTestNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr; HWND hwndWizard; HWND hwndSlider; BOOL fVoiceDetected; // Get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
// If we heard a voice, go to the speaker test page.
// Otherwise, go to the mic failed page
psinfo->GetVoiceDetected(&fVoiceDetected); if (fVoiceDetected) { // save the current recording slider position
hwndSlider = GetDlgItem(hDlg, IDC_RECVOL_SLIDER); if (hwndSlider == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", GetLastError()); } else { psinfo->SetInputVolumeSliderPos((LONG)SendMessage(hwndSlider, TBM_GETPOS, 0, 0)); }
// record the mic test result in the registry
psinfo->SetMicDetected(REGVAL_PASSED);
// move on to the speaker test.
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_SPEAKER_TEST); } else { hr = psinfo->ShutdownLoopbackThread(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, code: %i", hr); }
// record the mic test result in the registry
psinfo->SetMicDetected(REGVAL_FAILED);
// go to the mic test failed page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_MICTEST_FAILED); }
DPF_EXIT(); return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestBackHandler"
BOOL MicTestBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr; HWND hwndWizard; BOOL fVoiceDetected; // Get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
hr = psinfo->ShutdownLoopbackThread(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, code: %i", hr); }
// shutdown the any volume controls we launched
psinfo->CloseWindowsVolumeControl(TRUE); psinfo->CloseWindowsVolumeControl(FALSE);
// make it look like the mic test was never run
psinfo->SetMicDetected(REGVAL_NOTRUN);
// go back to the full duplex test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXTEST);
DPF_EXIT(); return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestVScrollHandler"
BOOL MicTestVScrollHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
HWND hwndSlider; DWORD dwSliderPos;
psinfo->GetHWNDInputVolumeSlider(&hwndSlider); if (hwndSlider == (HWND)lParam) { // the user is moving the input slider
dwSliderPos = (DWORD) SendMessage(hwndSlider, TBM_GETPOS, 0, 0);
// set the input volume to the user's request
psinfo->SetRecordVolume(AmpFactorToDB(DBToAmpFactor(DSBVOLUME_MAX)-dwSliderPos)); } DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestRecAdvancedHandler"
BOOL MicTestRecAdvancedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
HWND hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed"); DPF_EXIT(); return FALSE; } psinfo->LaunchWindowsVolumeControl(hwndWizard, TRUE);
DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "LoopbackTestThreadProc"
DWORD WINAPI LoopbackTestThreadProc(LPVOID lpvParam) { DPF_ENTER(); CSupervisorInfo* psinfo; HRESULT hr; LONG lRet; HWND hwnd; LPDIRECTPLAYVOICESERVER lpdpvs; LPDIRECTPLAYVOICECLIENT lpdpvc; PDIRECTPLAY8SERVER lpdp8; DWORD dwRet; HANDLE hEvent; DWORD dwWaveOutId; DWORD dwWaveInId; HWND hwndWizard; GUID guidCaptureDevice; GUID guidRenderDevice; DWORD dwFlags; DWORD dwSize; PDVSOUNDDEVICECONFIG pdvsdc = NULL; PBYTE pdvsdcBuffer = NULL; BOOL fLoopbackStarted = FALSE; psinfo = (CSupervisorInfo*)lpvParam; psinfo->GetHWNDDialog(&hwnd); psinfo->GetHWNDWizard(&hwndWizard); psinfo->GetCaptureDevice(&guidCaptureDevice); psinfo->GetRenderDevice(&guidRenderDevice); psinfo->GetLoopbackFlags(&dwFlags);
lpdpvs = NULL; lpdpvc = NULL; lpdp8 = NULL;
// new thread, init COM
hr = COM_CoInitialize(NULL);
if( FAILED( hr ) ) { Diagnostics_Write(DVF_ERRORLEVEL, "COM_CoInitialize failed, code: %i", hr); if (!PostMessage(hwnd, WM_APP_LOOPBACK_RUNNING, 0, (LPARAM)hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "PostMessage failed, code: %i", lRet); } goto error_cleanup; }
hr = StartDirectPlay( &lpdp8 );
if( FAILED( hr ) ) { Diagnostics_Write(DVF_ERRORLEVEL, "StartDirectPlay failed, code: 0x%x", hr); goto error_cleanup; }
hr = StartLoopback( &lpdpvs, &lpdpvc, &lpdp8, (LPVOID)psinfo, hwndWizard, guidCaptureDevice, guidRenderDevice, dwFlags);
if (FAILED(hr) ) { Diagnostics_Write(DVF_ERRORLEVEL, "StartLoopback failed, code: %i", hr); if (!PostMessage(hwnd, WM_APP_LOOPBACK_RUNNING, 0, (LPARAM)hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "PostMessage failed, code: %i", lRet); } goto error_cleanup; }
psinfo->SetLoopbackRunning( TRUE );
if( !(dwFlags & DVSOUNDCONFIG_HALFDUPLEX) && hr == DV_HALFDUPLEX ) { Diagnostics_Write(DVF_ERRORLEVEL, "StartLoopback failed with half duplex when expecting full duplex", hr); if (!PostMessage(hwnd, WM_APP_LOOPBACK_RUNNING, 0, (LPARAM)hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "PostMessage failed, code: %i", lRet); } goto error_cleanup; }
// save the voice client interface for the other threads to play with
psinfo->SetDPVC(lpdpvc);
dwSize = 0; hr = lpdpvc->GetSoundDeviceConfig(pdvsdc, &dwSize);
if( hr != DVERR_BUFFERTOOSMALL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "GetSoundDeviceConfig failed, hr: %i", hr ); if (!FAILED(hr)) { // map success codes to a generic failure, since we
// did not expect success
hr = DVERR_GENERIC; } goto error_cleanup; }
pdvsdcBuffer = new BYTE[dwSize];
if( pdvsdcBuffer == NULL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc failure" ); hr = DVERR_OUTOFMEMORY; goto error_cleanup; }
pdvsdc = (PDVSOUNDDEVICECONFIG) pdvsdcBuffer; pdvsdc->dwSize = sizeof( DVSOUNDDEVICECONFIG );
hr = lpdpvc->GetSoundDeviceConfig(pdvsdc, &dwSize); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "GetSoundDeviceConfig failed, hr: %i", hr); goto error_cleanup; }
hr = DV_MapGUIDToWaveID(FALSE, pdvsdc->guidPlaybackDevice, &dwWaveOutId); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DV_MapGUIDToWaveID failed, hr: %i", hr); goto error_cleanup; } hr = psinfo->SetWaveOutId(dwWaveOutId); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "SetWaveOutId failed, hr: %i", hr); goto error_cleanup; } hr = DV_MapGUIDToWaveID(TRUE, pdvsdc->guidCaptureDevice, &dwWaveInId); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "DV_MapGUIDToWaveID failed, hr: %i", hr); goto error_cleanup; } psinfo->SetWaveInId(dwWaveInId); psinfo->SetDeviceFlags( pdvsdc->dwFlags );
// inform the app that loopback is up and running.
hr = DV_OK; // Also send along the flags from GetSoundDeviceConfig
if (!PostMessage(hwnd, WM_APP_LOOPBACK_RUNNING, 0, (LPARAM)hr)) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "PostMessage failed, code: %i", lRet); goto error_cleanup; }
// wait on the shutdown event
hr = psinfo->WaitForLoopbackShutdownEvent(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "WaitForLoopbackShutdown failed, code: %i", hr); goto error_cleanup; }
psinfo->SetLoopbackRunning( FALSE);
delete [] pdvsdcBuffer; pdvsdcBuffer = NULL;
// Null out the interface pointer in sinfo
psinfo->SetDPVC(NULL);
// shutdown the loopback test
hr = StopLoopback(lpdpvs, lpdpvc, lpdp8); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "StopLoopback failed, code: %i", hr); goto error_cleanup; }
hr = StopDirectPlay( lpdp8 );
lpdp8 = NULL;
if( FAILED( hr ) ) { Diagnostics_Write(DVF_ERRORLEVEL, "StopDirectPlay failed, code: %i", hr); goto error_cleanup; }
// Signal the loopback thread exit event
psinfo->SignalLoopbackThreadDone();
COM_CoUninitialize(); DPF_EXIT(); return DV_OK;
error_cleanup: if (pdvsdcBuffer != NULL) { delete [] pdvsdcBuffer; }
if (fLoopbackStarted) { StopLoopback(lpdpvs, lpdpvc, lpdp8); }
if( lpdp8 ) { StopDirectPlay( lpdp8 ); }
psinfo->SetLoopbackRunning( FALSE);
psinfo->SignalLoopbackThreadDone(); COM_CoUninitialize(); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestResetHandler"
BOOL MicTestResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CompleteProc"
INT_PTR CALLBACK CompleteProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : fRet = CompleteInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = CompleteSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZFINISH : fRet = CompleteFinishHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = CompleteResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } break;
default: break; }
DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "CompleteInitDialogHandler"
BOOL CompleteInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfTitle; HRESULT hr = DV_OK; // Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetTitleFont(&hfTitle); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfTitle, (LPARAM)TRUE);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CompleteSetActiveHandler"
BOOL CompleteSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard; HWND hwndParent = NULL; HANDLE hEvent; HRESULT hr;
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { // log it, and return, don't know how to terminate the wizard properly
// without this handle!
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(NULL); psinfo->SetHWNDOutputPeak(NULL); psinfo->SetHWNDInputVolumeSlider(NULL); psinfo->SetHWNDOutputVolumeSlider(NULL);
PropSheet_SetWizButtons(hwndWizard, PSWIZB_FINISH);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CompleteFinishHandler"
BOOL CompleteFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
psinfo->Finish(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CompleteResetHandler"
BOOL CompleteResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedProc"
INT_PTR CALLBACK MicTestFailedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); LONG lRet; BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : MicTestFailedInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = MicTestFailedSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : fRet = MicTestFailedBackHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = MicTestFailedResetHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZFINISH : fRet = MicTestFailedFinishHandler(hDlg, message, wParam, lParam, psinfo); break; default : break; } break;
default: break; }
DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedInitDialogHandler"
BOOL MicTestFailedInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfTitle; HICON hIcon; HRESULT hr = DV_OK;
// Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetTitleFont(&hfTitle); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfTitle, (LPARAM)TRUE);
// load the warning icon
hIcon = LoadIcon(NULL, IDI_WARNING); SendDlgItemMessage(hDlg, IDC_WARNINGICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
DPF_EXIT(); return FALSE;
// error block
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedSetActiveHandler"
BOOL MicTestFailedSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard; HWND hwndParent = NULL; HWND hwndPeak; HANDLE hEvent; HRESULT hr;
PlaySound( _T("SystemExclamation"), NULL, SND_ASYNC );
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { // log it, and return, don't know how to terminate the wizard properly
// without this handle!
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(NULL); psinfo->SetHWNDOutputPeak(NULL); psinfo->SetHWNDInputVolumeSlider(NULL); psinfo->SetHWNDOutputVolumeSlider(NULL);
// enable the finish and back buttons
PropSheet_SetWizButtons(hwndWizard, PSWIZB_BACK|PSWIZB_FINISH);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedRecordStopHandler"
BOOL MicTestFailedRecordStopHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedBackHandler"
BOOL MicTestFailedBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
// go back to the mic test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_MICTEST);
DPF_EXIT(); return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedResetHandler"
BOOL MicTestFailedResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "MicTestFailedFinishHandler"
BOOL MicTestFailedFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
psinfo->Finish();
DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestProc"
INT_PTR CALLBACK SpeakerTestProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); LONG lRet; BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : SpeakerTestInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = SpeakerTestSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZNEXT : fRet = SpeakerTestNextHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : fRet = SpeakerTestBackHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = SpeakerTestResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_RECADVANCED: fRet = SpeakerTestRecAdvancedHandler(hDlg, message, wParam, lParam, psinfo); break;
case IDC_OUTADVANCED: fRet = SpeakerTestOutAdvancedHandler(hDlg, message, wParam, lParam, psinfo); break;
default: break; } break; case WM_VSCROLL: fRet = SpeakerTestVScrollHandler(hDlg, message, wParam, lParam, psinfo); break; default: break; }
DPF_ENTER(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestInitDialogHandler"
BOOL SpeakerTestInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfBold; HWND hwndRecPeak; HWND hwndOutPeak; HWND hwndRecSlider; HWND hwndOutSlider; HRESULT hr = DV_OK; // Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetBoldFont(&hfBold); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfBold, (LPARAM)TRUE);
// Init the recording peak meter
hwndRecPeak = GetDlgItem(hDlg, IDC_RECPEAKMETER); if (hwndRecPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndRecPeak, PM_SETMIN, 0, 0); SendMessage(hwndRecPeak, PM_SETMAX, 0, 99); SendMessage(hwndRecPeak, PM_SETCUR, 0, 0);
// Init the recording volume slider
hwndRecSlider = GetDlgItem(hDlg, IDC_RECVOL_SLIDER); if (hwndRecSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndRecSlider, TBM_SETRANGEMIN, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndRecSlider, TBM_SETRANGEMAX, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN)); SendMessage(hwndRecSlider, TBM_SETPOS, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndRecSlider, TBM_SETTICFREQ, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/10, 0); SendMessage(hwndRecSlider, TBM_SETLINESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/20); SendMessage(hwndRecSlider, TBM_SETPAGESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/5);
// Init the playback peak meter
hwndOutPeak = GetDlgItem(hDlg, IDC_OUTPEAKMETER); if (hwndOutPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndOutPeak, PM_SETMIN, 0, 0); SendMessage(hwndOutPeak, PM_SETMAX, 0, 99); SendMessage(hwndOutPeak, PM_SETCUR, 0, 0);
// Init the playback volume slider
hwndOutSlider = GetDlgItem(hDlg, IDC_OUTVOL_SLIDER); if (hwndOutSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndOutSlider, TBM_SETRANGEMIN, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndOutSlider, TBM_SETRANGEMAX, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN)); SendMessage(hwndOutSlider, TBM_SETPOS, 0, DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MAX)); SendMessage(hwndOutSlider, TBM_SETTICFREQ, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/10, 0); SendMessage(hwndOutSlider, TBM_SETLINESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/20); SendMessage(hwndOutSlider, TBM_SETPAGESIZE, 0, (DBToAmpFactor(DSBVOLUME_MAX) - DBToAmpFactor(DSBVOLUME_MIN))/5);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestSetActiveHandler"
BOOL SpeakerTestSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndRecPeak; HWND hwndOutPeak; HWND hwndRecSlider; HWND hwndOutSlider; HANDLE hEvent; HRESULT hr = DV_OK; DWORD dwVolume; HWND hwndRecAdvanced;
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Reset the recording peak meter
hwndRecPeak = GetDlgItem(hDlg, IDC_RECPEAKMETER); if (hwndRecPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndRecPeak, PM_SETCUR, 0, 0);
// set the recording volume slider to match
// the recording volume slider from the mic
// test page.
hwndRecSlider = GetDlgItem(hDlg, IDC_RECVOL_SLIDER); if (hwndRecSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
hwndRecAdvanced = GetDlgItem( hDlg, IDC_RECADVANCED ); if (hwndRecAdvanced == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = lRet; goto error_cleanup; } DWORD dwDeviceFlags;
psinfo->GetDeviceFlags( &dwDeviceFlags );
if( dwDeviceFlags & DVSOUNDCONFIG_NORECVOLAVAILABLE ) { EnableWindow( hwndRecSlider, FALSE ); EnableWindow( hwndRecAdvanced, FALSE ); } LONG lPos; psinfo->GetInputVolumeSliderPos(&lPos); SendMessage(hwndRecSlider, TBM_SETPOS, 1, lPos);
// Reset the playback peak meter
hwndOutPeak = GetDlgItem(hDlg, IDC_OUTPEAKMETER); if (hwndOutPeak == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } SendMessage(hwndOutPeak, PM_SETCUR, 0, 0);
// Grey out the playback volume slider - until we come back
// to fix it
hwndOutSlider = GetDlgItem(hDlg, IDC_OUTVOL_SLIDER); if (hwndOutSlider == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// Get the current waveOut volume and set the slider to that position
hr = psinfo->GetWaveOutVolume(&dwVolume); if (FAILED(hr)) { // couldn't get the volume - set the slider to top
SendMessage(hwndOutSlider, TBM_SETPOS, 1, SendMessage(hwndOutSlider, TBM_GETRANGEMIN, 0, 0)); // disable the slider
EnableWindow(hwndOutSlider, FALSE); } else { SendMessage(hwndOutSlider, TBM_SETPOS, 1, SendMessage(hwndOutSlider, TBM_GETRANGEMAX, 0, 0) - dwVolume); }
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(hwndRecPeak); psinfo->SetHWNDOutputPeak(hwndOutPeak); psinfo->SetHWNDInputVolumeSlider(hwndRecSlider); psinfo->SetHWNDOutputVolumeSlider(hwndOutSlider);
// unmute the output
hr = psinfo->Unmute(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "Unmute failed, code: %i", hr); goto error_cleanup; } // enable the next button
PropSheet_SetWizButtons(hwndWizard, PSWIZB_BACK|PSWIZB_NEXT);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestNextHandler"
BOOL SpeakerTestNextHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr = DV_OK; HWND hwndWizard = NULL; HWND hwndParent = NULL;
// get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
// shutdown the loopback test
hr = psinfo->ShutdownLoopbackThread(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, code: %i", hr); goto error_cleanup; }
// close any volume controls that are open.
psinfo->CloseWindowsVolumeControl(TRUE); psinfo->CloseWindowsVolumeControl(FALSE);
// the next page is the completion page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_COMPLETE);
DPF_EXIT(); return TRUE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestBackHandler"
BOOL SpeakerTestBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); HRESULT hr = DV_OK; HWND hwndWizard = NULL; HWND hwndParent = NULL;
// get the parent window
psinfo->GetHWNDWizard(&hwndWizard);
// shutdown the loopback test, so the mic test
// page can start fresh.
hr = psinfo->ShutdownLoopbackThread(); if (FAILED(hr)) { Diagnostics_Write(DVF_ERRORLEVEL, "ShutdownLoopbackThread failed, hr: %i", hr); goto error_cleanup; }
// close the output volume control, if showing
psinfo->CloseWindowsVolumeControl(FALSE);
// go back to the mic test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_MICTEST);
DPF_EXIT(); return TRUE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestResetHandler"
BOOL SpeakerTestResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestVScrollHandler"
BOOL SpeakerTestVScrollHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
HWND hwndSlider; DWORD dwSliderPos;
psinfo->GetHWNDInputVolumeSlider(&hwndSlider); if (hwndSlider == (HWND)lParam) { // the user is moving the input slider
dwSliderPos = (DWORD)SendMessage(hwndSlider, TBM_GETPOS, 0, 0);
// set the input volume to the user's request
psinfo->SetRecordVolume(AmpFactorToDB(DBToAmpFactor(DSBVOLUME_MAX)-dwSliderPos)); }
psinfo->GetHWNDOutputVolumeSlider(&hwndSlider); if (hwndSlider == (HWND)lParam) { // the user is moving the output slider
dwSliderPos = (DWORD) SendMessage(hwndSlider, TBM_GETPOS, 0, 0);
// set the output volume
psinfo->SetWaveOutVolume( ((DWORD) SendMessage(hwndSlider, TBM_GETRANGEMAX, 0, 0)) - dwSliderPos); } DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestRecAdvancedHandler"
BOOL SpeakerTestRecAdvancedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
HWND hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed"); DPF_EXIT(); return FALSE; } psinfo->LaunchWindowsVolumeControl(hwndWizard, TRUE);
DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "SpeakerTestOutAdvancedHandler"
BOOL SpeakerTestOutAdvancedHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
HWND hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed"); DPF_EXIT(); return FALSE; } psinfo->LaunchWindowsVolumeControl(hwndWizard, FALSE);
DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexFailedProc"
INT_PTR CALLBACK FullDuplexFailedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : fRet = FullDuplexFailedInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = FullDuplexFailedSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZFINISH : fRet = FullDuplexFailedFinishHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : fRet = FullDuplexFailedBackHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_RESET : fRet = FullDuplexFailedResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } break;
default: break; }
DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexFailedInitDialogHandler"
BOOL FullDuplexFailedInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfTitle; HICON hIcon; HRESULT hr = DV_OK;
// Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetTitleFont(&hfTitle); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfTitle, (LPARAM)TRUE);
// load the warning icon
hIcon = LoadIcon(NULL, IDI_WARNING); SendDlgItemMessage(hDlg, IDC_WARNINGICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexFailedSetActiveHandler"
BOOL FullDuplexFailedSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard; HWND hwndParent = NULL; HANDLE hEvent; HRESULT hr;
PlaySound( _T("SystemExclamation"), NULL, SND_ASYNC );
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(NULL); psinfo->SetHWNDOutputPeak(NULL); psinfo->SetHWNDInputVolumeSlider(NULL); psinfo->SetHWNDOutputVolumeSlider(NULL);
PropSheet_SetWizButtons(hwndWizard, PSWIZB_BACK|PSWIZB_FINISH);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexFailedFinishHandler"
BOOL FullDuplexFailedFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); psinfo->Finish(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexFailedResetHandler"
BOOL FullDuplexFailedResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexFailedBackHandler"
BOOL FullDuplexFailedBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
// go back to the full duplex test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXTEST); DPF_EXIT(); return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "HalfDuplexFailedProc"
INT_PTR CALLBACK HalfDuplexFailedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DPF_ENTER(); BOOL fRet; LPNMHDR lpnm; CSupervisorInfo* psinfo = (CSupervisorInfo*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
fRet = FALSE; switch (message) { case WM_INITDIALOG : fRet = HalfDuplexFailedInitDialogHandler(hDlg, message, wParam, lParam, psinfo); break;
case WM_NOTIFY : lpnm = (LPNMHDR) lParam;
switch (lpnm->code) { case PSN_SETACTIVE : fRet = HalfDuplexFailedSetActiveHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZFINISH : fRet = HalfDuplexFailedFinishHandler(hDlg, message, wParam, lParam, psinfo); break;
case PSN_WIZBACK : fRet = HalfDuplexFailedBackHandler(hDlg, message, wParam, lParam, psinfo); break; case PSN_RESET : fRet = HalfDuplexFailedResetHandler(hDlg, message, wParam, lParam, psinfo); break;
default : break; } break;
default: break; }
DPF_EXIT(); return fRet; }
#undef DPF_MODNAME
#define DPF_MODNAME "HalfDuplexFailedInitDialogHandler"
BOOL HalfDuplexFailedInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard = NULL; HWND hwndParent = NULL; HWND hwndControl; HFONT hfTitle; HICON hIcon; HRESULT hr = DV_OK;
// Get the shared data from PROPSHEETPAGE lParam value
// and load it into GWLP_USERDATA
psinfo = (CSupervisorInfo*)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)psinfo); // Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } hwndControl = GetDlgItem(hDlg, IDC_TITLE); if (hwndControl == NULL) { // error, log it and bail
lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; } psinfo->GetTitleFont(&hfTitle); (void)::SendMessage(hwndControl, WM_SETFONT, (WPARAM)hfTitle, (LPARAM)TRUE);
// load the warning icon
hIcon = LoadIcon(NULL, IDI_WARNING); SendDlgItemMessage(hDlg, IDC_WARNINGICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "HalfDuplexFailedSetActiveHandler"
BOOL HalfDuplexFailedSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); LONG lRet; HWND hwndWizard; HWND hwndParent = NULL; HANDLE hEvent; HRESULT hr;
PlaySound( _T("SystemExclamation"), NULL, SND_ASYNC );
// Get the parent window
hwndWizard = GetParent(hDlg); if (hwndWizard == NULL) { lRet = GetLastError(); Diagnostics_Write(DVF_ERRORLEVEL, "GetParent failed, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
// set the HWNDs
psinfo->SetHWNDWizard(hwndWizard); psinfo->SetHWNDDialog(hDlg); psinfo->SetHWNDProgress(NULL); psinfo->SetHWNDInputPeak(NULL); psinfo->SetHWNDOutputPeak(NULL); psinfo->SetHWNDInputVolumeSlider(NULL); psinfo->SetHWNDOutputVolumeSlider(NULL);
PropSheet_SetWizButtons(hwndWizard, PSWIZB_BACK|PSWIZB_FINISH);
DPF_EXIT(); return FALSE;
error_cleanup: psinfo->GetHWNDParent(&hwndParent); DV_DisplayErrorBox(hr, hwndParent); psinfo->SetError(hr); psinfo->Abort(hDlg, hr); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "HalfDuplexFailedFinishHandler"
BOOL HalfDuplexFailedFinishHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); psinfo->Finish(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "HalfDuplexFailedResetHandler"
BOOL HalfDuplexFailedResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER(); DPF_EXIT(); return FALSE; }
#undef DPF_MODNAME
#define DPF_MODNAME "HalfDuplexFailedBackHandler"
BOOL HalfDuplexFailedBackHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, CSupervisorInfo* psinfo) { DPF_ENTER();
// go back to the full duplex test page
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_FULLDUPLEXTEST); DPF_EXIT(); return TRUE; }
|