394 lines
9.4 KiB
C++
394 lines
9.4 KiB
C++
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dxvt.cpp
|
|
* Content: Full Duplex Test main program.
|
|
* History:
|
|
* Date By Reason
|
|
* ============
|
|
* 08/19/99 pnewson created
|
|
* 09/02/99 pnewson renamed to dxvt.cpp from fdtest.cpp
|
|
* 11/01/99 rodtoll Bug #113726 - Voxware integration now uses COM
|
|
* and this module uses LoadLibrary so we require
|
|
* a CoInitialize() call.
|
|
* 01/21/2000 pnewson Running this program with no command line options
|
|
* now does nothing, since the cpanel is the correct
|
|
* launch point now.
|
|
* 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
|
|
* 04/19/2000 pnewson Error handling cleanup
|
|
* removed obsolete retrocfg.h dependency
|
|
* 06/28/2000 rodtoll Prefix Bug #38026
|
|
* 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard
|
|
* 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h, added STR_* and strutils.h
|
|
* 04/02/2001 simonpow Bug #354859 Fixes for PREfast (BOOL casts on DVGUIDFromString calls)
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
#include <initguid.h>
|
|
#include <dplobby.h>
|
|
#include <commctrl.h>
|
|
#include <mmsystem.h>
|
|
#include <dsoundp.h>
|
|
#include <dsprv.h>
|
|
#include "dvoice.h"
|
|
|
|
#include "creg.h"
|
|
#include "osind.h"
|
|
#include "priority.h"
|
|
#include "fulldup.h"
|
|
#include "fdtcfg.h"
|
|
#include "dndbg.h"
|
|
#include "dsound.h"
|
|
#include "supervis.h"
|
|
#include "guidutil.h"
|
|
#include "strutils.h"
|
|
#include "comutil.h"
|
|
#include "diagnos.h"
|
|
|
|
#include "..\..\bldcfg\dpvcfg.h"
|
|
|
|
#undef DPF_SUBCOMP
|
|
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
|
|
|
|
|
|
#define DPVOICE_REGISTRY_DUMPDIAGNOSTICS L"InitDiagnostics"
|
|
|
|
struct DPVSETUP_PARAMETERS
|
|
{
|
|
BOOL fPriority;
|
|
BOOL fFullDuplex;
|
|
BOOL fTest;
|
|
GUID guidRender;
|
|
GUID guidCapture;
|
|
};
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ProcessCommandLine"
|
|
BOOL ProcessCommandLine( TCHAR *pstrCommandLine, DPVSETUP_PARAMETERS* pParameters )
|
|
{
|
|
TCHAR *pNextToken = NULL;
|
|
WCHAR wszGuidString[GUID_STRING_LEN];
|
|
BOOL fRet;
|
|
HRESULT hr=S_OK;
|
|
|
|
DPF_ENTER();
|
|
|
|
ZeroMemory(pParameters, sizeof(DPVSETUP_PARAMETERS));
|
|
|
|
// default to the default voice devices
|
|
pParameters->guidRender = DSDEVID_DefaultVoicePlayback;
|
|
pParameters->guidCapture = DSDEVID_DefaultVoiceCapture;
|
|
|
|
pNextToken = _tcstok(pstrCommandLine, _T(" "));
|
|
|
|
// skip dpvsetup portion of command-line.
|
|
pNextToken = _tcstok( NULL, _T(" ") );
|
|
|
|
while( pNextToken != NULL )
|
|
{
|
|
if( _tcsicmp(pNextToken, _T("/T")) == 0
|
|
|| _tcsicmp(pNextToken, _T("/TEST")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-T")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-TEST")) == 0
|
|
|| _tcsicmp(pNextToken, _T("TEST")) == 0)
|
|
{
|
|
pParameters->fTest = TRUE;
|
|
}
|
|
else if(_tcsicmp(pNextToken, _T("/F")) == 0
|
|
|| _tcsicmp(pNextToken, _T("/FULLDUPLEX")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-F")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-FULLDUPLEX")) == 0
|
|
|| _tcsicmp(pNextToken, _T("FULLDUPLEX")) == 0)
|
|
{
|
|
pParameters->fFullDuplex = TRUE;
|
|
}
|
|
else if(_tcsicmp(pNextToken, _T("/P")) == 0
|
|
|| _tcsicmp(pNextToken, _T("/PRIORITY")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-P")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-PRIORITY")) == 0
|
|
|| _tcsicmp(pNextToken, _T("PRIORITY")) == 0)
|
|
{
|
|
pParameters->fPriority = TRUE;
|
|
}
|
|
else if(_tcsicmp(pNextToken, _T("/R")) == 0
|
|
|| _tcsicmp(pNextToken, _T("/RENDER")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-R")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-RENDER")) == 0)
|
|
{
|
|
// get the render device guid
|
|
pNextToken = _tcstok( pstrCommandLine, _T(" ") );
|
|
if (pNextToken != NULL)
|
|
{
|
|
if (_tcslen(pstrCommandLine) != GUID_STRING_LEN - 1)
|
|
{
|
|
// command line guid string too long, error
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "guid on command line wrong size");
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UNICODE
|
|
wcscpy( wszGuidString, pNextToken );
|
|
#else
|
|
if ( FAILED(STR_jkAnsiToWide(wszGuidString, pNextToken, GUID_STRING_LEN)))
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "STR_jkAnsiToWide failed");
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
hr=DVGUIDFromString(wszGuidString, &pParameters->guidRender);
|
|
if (FAILED(hr))
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVGUIDFromString failed");
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( _tcsicmp(pNextToken, _T("/C")) == 0
|
|
|| _tcsicmp(pNextToken, _T("/CAPTURE")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-C")) == 0
|
|
|| _tcsicmp(pNextToken, _T("-CAPTURE")) == 0)
|
|
{
|
|
// get the render device guid
|
|
pNextToken = _tcstok( pstrCommandLine, _T(" ") );
|
|
if (pNextToken != NULL)
|
|
{
|
|
if (_tcslen(pstrCommandLine) != GUID_STRING_LEN - 1)
|
|
{
|
|
// command line guid string too long, error
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "guid on command line wrong size");
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UNICODE
|
|
wcscpy( wszGuidString, pNextToken );
|
|
#else
|
|
if ( FAILED(STR_jkAnsiToWide(wszGuidString, pNextToken, GUID_STRING_LEN)))
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "STR_jkAnsiToWide failed");
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
hr=DVGUIDFromString(wszGuidString, &pParameters->guidCapture);
|
|
if (FAILED(hr))
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVGUIDFromString failed");
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
pNextToken = _tcstok( NULL, _T(" ") );
|
|
}
|
|
|
|
// check to make sure only one of test, fullduplex, or priority was specified.
|
|
int i = 0;
|
|
if (pParameters->fTest)
|
|
{
|
|
++i;
|
|
}
|
|
if (pParameters->fFullDuplex)
|
|
{
|
|
++i;
|
|
}
|
|
if (pParameters->fPriority)
|
|
{
|
|
++i;
|
|
}
|
|
if (i > 1)
|
|
{
|
|
DPF_EXIT();
|
|
return FALSE;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return TRUE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetDiagnosticsSetting"
|
|
BOOL GetDiagnosticsSetting()
|
|
{
|
|
CRegistry cregSettings;
|
|
|
|
BOOL fResult = FALSE;
|
|
|
|
if( !cregSettings.Open( HKEY_CURRENT_USER, DPVOICE_REGISTRY_BASE, FALSE, TRUE ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
cregSettings.ReadBOOL( DPVOICE_REGISTRY_DUMPDIAGNOSTICS, fResult );
|
|
|
|
return fResult;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "WinMain"
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, CHAR *szOriginalCmdLine, int iCmdShow)
|
|
{
|
|
HINSTANCE hResDLLInstance = NULL;
|
|
HRESULT hr;
|
|
DPVSETUP_PARAMETERS dpvsetupParam;
|
|
BOOL fCoInitialized = FALSE;
|
|
BOOL fDNOSInitialized = FALSE;
|
|
BOOL fDiagnostics = FALSE;
|
|
TCHAR *szCmdLine = GetCommandLine();
|
|
|
|
DPF_ENTER();
|
|
|
|
hr = COM_CoInitialize(NULL);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
MessageBox( NULL, _T("Error initializing COM"), _T("Error"), MB_OK|MB_ICONERROR);
|
|
hr = DVERR_GENERIC;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
fCoInitialized = TRUE;
|
|
|
|
if (!DNOSIndirectionInit())
|
|
{
|
|
MessageBox( NULL, _T("Error initializing OS indirection layer"), _T("Error"), MB_OK|MB_ICONERROR);
|
|
hr = DVERR_OUTOFMEMORY;
|
|
goto error_cleanup;
|
|
}
|
|
fDNOSInitialized = TRUE;
|
|
|
|
fDiagnostics = GetDiagnosticsSetting();
|
|
|
|
if (!ProcessCommandLine(szCmdLine, &dpvsetupParam))
|
|
{
|
|
MessageBox(NULL, _T("Bad Command Line Parameters"), _T("Error"), MB_OK|MB_ICONERROR);
|
|
hr = DVERR_INVALIDPARAM;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
hResDLLInstance = LoadLibraryA(gc_szResDLLName);
|
|
if (hResDLLInstance == NULL)
|
|
{
|
|
MessageBox(NULL, _T("Unable to load resource DLL - exiting program"), _T("Error"), MB_OK|MB_ICONERROR);
|
|
hr = DVERR_GENERIC;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
if (dpvsetupParam.fPriority)
|
|
{
|
|
// This process is the one that opens dsound in
|
|
// priority mode and sets the primary buffer to various
|
|
// formats.
|
|
// use SEH to clean up any really nasty errors
|
|
__try
|
|
{
|
|
Diagnostics_Begin( fDiagnostics, "dpv_pri.txt" );
|
|
|
|
hr = PriorityProcess(hResDLLInstance, hPrevInstance, szCmdLine, iCmdShow);
|
|
|
|
Diagnostics_End();
|
|
|
|
}
|
|
__except(1)
|
|
{
|
|
hr = DVERR_GENERIC;
|
|
}
|
|
if( FAILED( hr ) )
|
|
{
|
|
goto error_cleanup;
|
|
}
|
|
}
|
|
else if (dpvsetupParam.fFullDuplex)
|
|
{
|
|
// This process is the one that performs the full duplex
|
|
// testing, in conjunction with the other process that
|
|
// sets the primary buffer format.
|
|
// use SEH to clean up any really nasty errors
|
|
__try
|
|
{
|
|
Diagnostics_Begin( fDiagnostics, "dpv_fd.txt" );
|
|
|
|
hr = FullDuplexProcess(hResDLLInstance, hPrevInstance, szCmdLine, iCmdShow);
|
|
|
|
Diagnostics_End();
|
|
}
|
|
__except(1)
|
|
{
|
|
hr = DVERR_GENERIC;
|
|
}
|
|
if( FAILED( hr ) )
|
|
{
|
|
goto error_cleanup;
|
|
}
|
|
}
|
|
else if (dpvsetupParam.fTest)
|
|
{
|
|
Diagnostics_Begin( fDiagnostics, "dpv_sup.txt" );
|
|
|
|
// The user wants this program to run the whole test on the default
|
|
// voice devices.
|
|
hr = SupervisorCheckAudioSetup(&dpvsetupParam.guidRender, &dpvsetupParam.guidCapture, NULL, 0);
|
|
|
|
Diagnostics_End();
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
goto error_cleanup;
|
|
}
|
|
}
|
|
|
|
// With no command line parameters, this process does nothing.
|
|
// You must know the secret handshake to get it to do something.
|
|
|
|
// no error checking, since we're on our way out anyway
|
|
FreeLibrary(hResDLLInstance);
|
|
hResDLLInstance = NULL;
|
|
DNOSIndirectionDeinit();
|
|
fDNOSInitialized = FALSE;
|
|
COM_CoUninitialize();
|
|
fCoInitialized = FALSE;
|
|
DPF_EXIT();
|
|
return DV_OK;
|
|
|
|
error_cleanup:
|
|
|
|
if (hResDLLInstance != NULL)
|
|
{
|
|
FreeLibrary(hResDLLInstance);
|
|
hResDLLInstance = NULL;
|
|
}
|
|
|
|
if (fDNOSInitialized == TRUE)
|
|
{
|
|
DNOSIndirectionDeinit();
|
|
fDNOSInitialized = FALSE;
|
|
}
|
|
|
|
if (fCoInitialized == TRUE)
|
|
{
|
|
COM_CoUninitialize();
|
|
fCoInitialized = FALSE;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|