windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dvoice/dxvt/dxvt.cpp
2020-09-26 16:20:57 +08:00

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;
}