Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

393 lines
9.4 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dxvt.cpp
  6. * Content: Full Duplex Test main program.
  7. * History:
  8. * Date By Reason
  9. * ============
  10. * 08/19/99 pnewson created
  11. * 09/02/99 pnewson renamed to dxvt.cpp from fdtest.cpp
  12. * 11/01/99 rodtoll Bug #113726 - Voxware integration now uses COM
  13. * and this module uses LoadLibrary so we require
  14. * a CoInitialize() call.
  15. * 01/21/2000 pnewson Running this program with no command line options
  16. * now does nothing, since the cpanel is the correct
  17. * launch point now.
  18. * 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
  19. * 04/19/2000 pnewson Error handling cleanup
  20. * removed obsolete retrocfg.h dependency
  21. * 06/28/2000 rodtoll Prefix Bug #38026
  22. * 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard
  23. * 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h, added STR_* and strutils.h
  24. * 04/02/2001 simonpow Bug #354859 Fixes for PREfast (BOOL casts on DVGUIDFromString calls)
  25. *
  26. ***************************************************************************/
  27. #include <windows.h>
  28. #include <tchar.h>
  29. #include <initguid.h>
  30. #include <dplobby.h>
  31. #include <commctrl.h>
  32. #include <mmsystem.h>
  33. #include <dsoundp.h>
  34. #include <dsprv.h>
  35. #include "dvoice.h"
  36. #include "creg.h"
  37. #include "osind.h"
  38. #include "priority.h"
  39. #include "fulldup.h"
  40. #include "fdtcfg.h"
  41. #include "dndbg.h"
  42. #include "dsound.h"
  43. #include "supervis.h"
  44. #include "guidutil.h"
  45. #include "strutils.h"
  46. #include "comutil.h"
  47. #include "diagnos.h"
  48. #include "..\..\bldcfg\dpvcfg.h"
  49. #undef DPF_SUBCOMP
  50. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  51. #define DPVOICE_REGISTRY_DUMPDIAGNOSTICS L"InitDiagnostics"
  52. struct DPVSETUP_PARAMETERS
  53. {
  54. BOOL fPriority;
  55. BOOL fFullDuplex;
  56. BOOL fTest;
  57. GUID guidRender;
  58. GUID guidCapture;
  59. };
  60. #undef DPF_MODNAME
  61. #define DPF_MODNAME "ProcessCommandLine"
  62. BOOL ProcessCommandLine( TCHAR *pstrCommandLine, DPVSETUP_PARAMETERS* pParameters )
  63. {
  64. TCHAR *pNextToken = NULL;
  65. WCHAR wszGuidString[GUID_STRING_LEN];
  66. BOOL fRet;
  67. HRESULT hr=S_OK;
  68. DPF_ENTER();
  69. ZeroMemory(pParameters, sizeof(DPVSETUP_PARAMETERS));
  70. // default to the default voice devices
  71. pParameters->guidRender = DSDEVID_DefaultVoicePlayback;
  72. pParameters->guidCapture = DSDEVID_DefaultVoiceCapture;
  73. pNextToken = _tcstok(pstrCommandLine, _T(" "));
  74. // skip dpvsetup portion of command-line.
  75. pNextToken = _tcstok( NULL, _T(" ") );
  76. while( pNextToken != NULL )
  77. {
  78. if( _tcsicmp(pNextToken, _T("/T")) == 0
  79. || _tcsicmp(pNextToken, _T("/TEST")) == 0
  80. || _tcsicmp(pNextToken, _T("-T")) == 0
  81. || _tcsicmp(pNextToken, _T("-TEST")) == 0
  82. || _tcsicmp(pNextToken, _T("TEST")) == 0)
  83. {
  84. pParameters->fTest = TRUE;
  85. }
  86. else if(_tcsicmp(pNextToken, _T("/F")) == 0
  87. || _tcsicmp(pNextToken, _T("/FULLDUPLEX")) == 0
  88. || _tcsicmp(pNextToken, _T("-F")) == 0
  89. || _tcsicmp(pNextToken, _T("-FULLDUPLEX")) == 0
  90. || _tcsicmp(pNextToken, _T("FULLDUPLEX")) == 0)
  91. {
  92. pParameters->fFullDuplex = TRUE;
  93. }
  94. else if(_tcsicmp(pNextToken, _T("/P")) == 0
  95. || _tcsicmp(pNextToken, _T("/PRIORITY")) == 0
  96. || _tcsicmp(pNextToken, _T("-P")) == 0
  97. || _tcsicmp(pNextToken, _T("-PRIORITY")) == 0
  98. || _tcsicmp(pNextToken, _T("PRIORITY")) == 0)
  99. {
  100. pParameters->fPriority = TRUE;
  101. }
  102. else if(_tcsicmp(pNextToken, _T("/R")) == 0
  103. || _tcsicmp(pNextToken, _T("/RENDER")) == 0
  104. || _tcsicmp(pNextToken, _T("-R")) == 0
  105. || _tcsicmp(pNextToken, _T("-RENDER")) == 0)
  106. {
  107. // get the render device guid
  108. pNextToken = _tcstok( pstrCommandLine, _T(" ") );
  109. if (pNextToken != NULL)
  110. {
  111. if (_tcslen(pstrCommandLine) != GUID_STRING_LEN - 1)
  112. {
  113. // command line guid string too long, error
  114. DPFX(DPFPREP, DVF_ERRORLEVEL, "guid on command line wrong size");
  115. DPF_EXIT();
  116. return FALSE;
  117. }
  118. else
  119. {
  120. #ifdef UNICODE
  121. wcscpy( wszGuidString, pNextToken );
  122. #else
  123. if ( FAILED(STR_jkAnsiToWide(wszGuidString, pNextToken, GUID_STRING_LEN)))
  124. {
  125. DPFX(DPFPREP, DVF_ERRORLEVEL, "STR_jkAnsiToWide failed");
  126. DPF_EXIT();
  127. return FALSE;
  128. }
  129. #endif
  130. hr=DVGUIDFromString(wszGuidString, &pParameters->guidRender);
  131. if (FAILED(hr))
  132. {
  133. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVGUIDFromString failed");
  134. DPF_EXIT();
  135. return FALSE;
  136. }
  137. }
  138. }
  139. }
  140. else if( _tcsicmp(pNextToken, _T("/C")) == 0
  141. || _tcsicmp(pNextToken, _T("/CAPTURE")) == 0
  142. || _tcsicmp(pNextToken, _T("-C")) == 0
  143. || _tcsicmp(pNextToken, _T("-CAPTURE")) == 0)
  144. {
  145. // get the render device guid
  146. pNextToken = _tcstok( pstrCommandLine, _T(" ") );
  147. if (pNextToken != NULL)
  148. {
  149. if (_tcslen(pstrCommandLine) != GUID_STRING_LEN - 1)
  150. {
  151. // command line guid string too long, error
  152. DPFX(DPFPREP, DVF_ERRORLEVEL, "guid on command line wrong size");
  153. DPF_EXIT();
  154. return FALSE;
  155. }
  156. else
  157. {
  158. #ifdef UNICODE
  159. wcscpy( wszGuidString, pNextToken );
  160. #else
  161. if ( FAILED(STR_jkAnsiToWide(wszGuidString, pNextToken, GUID_STRING_LEN)))
  162. {
  163. DPFX(DPFPREP, DVF_ERRORLEVEL, "STR_jkAnsiToWide failed");
  164. DPF_EXIT();
  165. return FALSE;
  166. }
  167. #endif
  168. hr=DVGUIDFromString(wszGuidString, &pParameters->guidCapture);
  169. if (FAILED(hr))
  170. {
  171. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVGUIDFromString failed");
  172. DPF_EXIT();
  173. return FALSE;
  174. }
  175. }
  176. }
  177. }
  178. else
  179. {
  180. DPF_EXIT();
  181. return FALSE;
  182. }
  183. pNextToken = _tcstok( NULL, _T(" ") );
  184. }
  185. // check to make sure only one of test, fullduplex, or priority was specified.
  186. int i = 0;
  187. if (pParameters->fTest)
  188. {
  189. ++i;
  190. }
  191. if (pParameters->fFullDuplex)
  192. {
  193. ++i;
  194. }
  195. if (pParameters->fPriority)
  196. {
  197. ++i;
  198. }
  199. if (i > 1)
  200. {
  201. DPF_EXIT();
  202. return FALSE;
  203. }
  204. DPF_EXIT();
  205. return TRUE;
  206. }
  207. #undef DPF_MODNAME
  208. #define DPF_MODNAME "GetDiagnosticsSetting"
  209. BOOL GetDiagnosticsSetting()
  210. {
  211. CRegistry cregSettings;
  212. BOOL fResult = FALSE;
  213. if( !cregSettings.Open( HKEY_CURRENT_USER, DPVOICE_REGISTRY_BASE, FALSE, TRUE ) )
  214. {
  215. return FALSE;
  216. }
  217. cregSettings.ReadBOOL( DPVOICE_REGISTRY_DUMPDIAGNOSTICS, fResult );
  218. return fResult;
  219. }
  220. #undef DPF_MODNAME
  221. #define DPF_MODNAME "WinMain"
  222. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, CHAR *szOriginalCmdLine, int iCmdShow)
  223. {
  224. HINSTANCE hResDLLInstance = NULL;
  225. HRESULT hr;
  226. DPVSETUP_PARAMETERS dpvsetupParam;
  227. BOOL fCoInitialized = FALSE;
  228. BOOL fDNOSInitialized = FALSE;
  229. BOOL fDiagnostics = FALSE;
  230. TCHAR *szCmdLine = GetCommandLine();
  231. DPF_ENTER();
  232. hr = COM_CoInitialize(NULL);
  233. if( FAILED( hr ) )
  234. {
  235. MessageBox( NULL, _T("Error initializing COM"), _T("Error"), MB_OK|MB_ICONERROR);
  236. hr = DVERR_GENERIC;
  237. goto error_cleanup;
  238. }
  239. fCoInitialized = TRUE;
  240. if (!DNOSIndirectionInit())
  241. {
  242. MessageBox( NULL, _T("Error initializing OS indirection layer"), _T("Error"), MB_OK|MB_ICONERROR);
  243. hr = DVERR_OUTOFMEMORY;
  244. goto error_cleanup;
  245. }
  246. fDNOSInitialized = TRUE;
  247. fDiagnostics = GetDiagnosticsSetting();
  248. if (!ProcessCommandLine(szCmdLine, &dpvsetupParam))
  249. {
  250. MessageBox(NULL, _T("Bad Command Line Parameters"), _T("Error"), MB_OK|MB_ICONERROR);
  251. hr = DVERR_INVALIDPARAM;
  252. goto error_cleanup;
  253. }
  254. hResDLLInstance = LoadLibraryA(gc_szResDLLName);
  255. if (hResDLLInstance == NULL)
  256. {
  257. MessageBox(NULL, _T("Unable to load resource DLL - exiting program"), _T("Error"), MB_OK|MB_ICONERROR);
  258. hr = DVERR_GENERIC;
  259. goto error_cleanup;
  260. }
  261. if (dpvsetupParam.fPriority)
  262. {
  263. // This process is the one that opens dsound in
  264. // priority mode and sets the primary buffer to various
  265. // formats.
  266. // use SEH to clean up any really nasty errors
  267. __try
  268. {
  269. Diagnostics_Begin( fDiagnostics, "dpv_pri.txt" );
  270. hr = PriorityProcess(hResDLLInstance, hPrevInstance, szCmdLine, iCmdShow);
  271. Diagnostics_End();
  272. }
  273. __except(1)
  274. {
  275. hr = DVERR_GENERIC;
  276. }
  277. if( FAILED( hr ) )
  278. {
  279. goto error_cleanup;
  280. }
  281. }
  282. else if (dpvsetupParam.fFullDuplex)
  283. {
  284. // This process is the one that performs the full duplex
  285. // testing, in conjunction with the other process that
  286. // sets the primary buffer format.
  287. // use SEH to clean up any really nasty errors
  288. __try
  289. {
  290. Diagnostics_Begin( fDiagnostics, "dpv_fd.txt" );
  291. hr = FullDuplexProcess(hResDLLInstance, hPrevInstance, szCmdLine, iCmdShow);
  292. Diagnostics_End();
  293. }
  294. __except(1)
  295. {
  296. hr = DVERR_GENERIC;
  297. }
  298. if( FAILED( hr ) )
  299. {
  300. goto error_cleanup;
  301. }
  302. }
  303. else if (dpvsetupParam.fTest)
  304. {
  305. Diagnostics_Begin( fDiagnostics, "dpv_sup.txt" );
  306. // The user wants this program to run the whole test on the default
  307. // voice devices.
  308. hr = SupervisorCheckAudioSetup(&dpvsetupParam.guidRender, &dpvsetupParam.guidCapture, NULL, 0);
  309. Diagnostics_End();
  310. if( FAILED( hr ) )
  311. {
  312. goto error_cleanup;
  313. }
  314. }
  315. // With no command line parameters, this process does nothing.
  316. // You must know the secret handshake to get it to do something.
  317. // no error checking, since we're on our way out anyway
  318. FreeLibrary(hResDLLInstance);
  319. hResDLLInstance = NULL;
  320. DNOSIndirectionDeinit();
  321. fDNOSInitialized = FALSE;
  322. COM_CoUninitialize();
  323. fCoInitialized = FALSE;
  324. DPF_EXIT();
  325. return DV_OK;
  326. error_cleanup:
  327. if (hResDLLInstance != NULL)
  328. {
  329. FreeLibrary(hResDLLInstance);
  330. hResDLLInstance = NULL;
  331. }
  332. if (fDNOSInitialized == TRUE)
  333. {
  334. DNOSIndirectionDeinit();
  335. fDNOSInitialized = FALSE;
  336. }
  337. if (fCoInitialized == TRUE)
  338. {
  339. COM_CoUninitialize();
  340. fCoInitialized = FALSE;
  341. }
  342. DPF_EXIT();
  343. return hr;
  344. }